从ES5迈向ES6:探索 JavaScript 新增声明命令与解构赋值的魅力


在这里插入图片描述



个人主页:学习前端的小z

个人专栏:JavaScript 精粹

本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论!
在这里插入图片描述


ES5、ES6介绍


文章目录

  • 💯声明命令 let、const
    • 🍟1 let声明符
      • 🎲1.1 基础特性
      • 🎲1.2 不进行变量提升
      • 🎲1.3 致死域(暂时性死区)
      • 🎲1.4 无法重复声明
      • 🎲1.5 块作用域 (block scope)
      • 🎲1.6 块作用域下的函数声明
    • 🍟2 const声明符
      • 🎲2.1 声明时必须赋值
      • 🎲2.2 值为对象
  • 💯解构赋值
    • 🍟1 数组解构
      • 🎲1.1 基础变量赋值
      • 🎲1.2 声明分别赋值
      • 🎲1.3 解构默认值
      • 🎲1.4 交换变量值
      • 🎲1.5 解析函数返回的数组
      • 🎲1.6 忽略返回值/跳过某项
      • 🎲1.7 赋值数组剩余值给一个变量
      • 🎲1.8 嵌套数组解构
    • 🍟2 对象解构
      • 🎲2.1 基础对象解构
      • 🎲2.2 无声明解构
      • 🎲2.3 赋值给新变量名
      • 🎲2.4 解构默认值
      • 🎲2.5 赋值给新变量名的同时提供默认值
      • 🎲2.6 嵌套对象和数组解构
      • 🎲2.7 可计算对象属性名与解构
      • 🎲2.8 同时使用数组和对象解构
      • 🎲2.9 注意点
    • 🍟3 函数参数的解构赋值
    • 🍟4 解构的用途
      • 🎲4.1 交换变量的值
      • 🎲4.2 从函数返回多个值
      • 🎲4.3 函数参数的定义
      • 🎲4.4 提取 JSON 数据
      • 🎲4.5 函数参数的默认值


在这里插入图片描述


💯声明命令 let、const

🍟1 let声明符

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

🎲1.1 基础特性

if(true){let a = 'let';var b = 'var';
}console.log(b); //var
console.log(a); //Uncaught ReferenceError: a is not defined---------------------------------------------------------//使用let,声明的变量仅在块级作用域内({ })有效,最后输出的是 6。
for(let i = 0; i < 10; i++){}
console.log(i); //Uncaught ReferenceError: i is not defined

上面代码在代码块之中,分别用letvar声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。

// 在循环体表达式中let声明迭代变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量
var a = [];
for (let i = 0; i < 10; i++) {a.push(function () {console.log(i);});
}
a[5](); // 5
// 在循环体表达式中let声明 和循环体中let 声明同名变量是不冲突的 设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。相当于每次循环{}内部都会单独开一个局部作用域
for (let i = 0; i < 3; i++) {let i = 'abc';console.log(i);
}

🎲1.2 不进行变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined

let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。 这一点需要特殊注意

// var 的情况
console.log(num); // 输出undefined
var num = 2;-------------------------// let 的情况
console.log(age); // 报错ReferenceError
let age = 16;

🎲1.3 致死域(暂时性死区)

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

//正常调用
let num = 10;
if (true) {console.log(num); //10
}------------------//if { }内部let为独立局部作用域 访问为 20
let num = 10;
if (true) {let num = 20;console.log(num); //20
}------------------//发生致死 因为fn局部作用域中有let声明num 所以在作用域内 不能先调用再使用let声明。
let num = 10;
function fn() {console.log(num); //Uncaught ReferenceError: Cannot access 'num' before initializationlet num = 20;
}
fn();------------------//typeof操作影响typeof num;
let num; //Uncaught ReferenceError: Cannot access 'num' before initialization

当程序的控制流程在新的作用域(module function 或 block 作用域)进行实例化时,在此作用域中用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

es6规定 let/const 会使区域形成封闭的作用域 若在声明之前使用变量就会发生错误, 在代码块内使用let命令声明变量之前 该变量都无法使用,称为“暂时性死区”(temporal dead zone,简称 TDZ)。总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。使用let 确保先 声明 再 使用 变量 不要混用let和var在同一个作用域链上 避免死区

🎲1.4 无法重复声明

let不允许在相同作用域内,重复声明同一个变量。

//发生致死 因为var会变量提升。
let num = 10;
if (true) {var num = 20; //Uncaught SyntaxError: Identifier 'num' has already been declaredconsole.log(num);
}

🎲1.5 块作用域 (block scope)

在ES5中,只全局作用域和函数作用域。这会导致函数作用域覆盖了全局作用域;亦或者循环中的变量泄露为全局变量。

EcmaScript 6引入了块级作用域(block scope),块级作用域只能在块中被访问,以下两种情况可以创建块级作用域的变量。

  • 在函数中

  • 在被{}包裹的块中

{var x = 10;
}
console.log(x); //10------------------{let x = 10;
}
console.log(x);//x is not defined------------------//函数有两个代码块,都声明了变量num,运行后输出 3。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量num,最后输出的值才是 6。
function fn() {let num = 3;if (true) {let num = 6;}console.log(num); // 3
}

🎲1.6 块作用域下的函数声明

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

function a() {console.log('我是全局作用域内声明的函数a');
}(function () {if (false) {function a() {console.log('我是块级作用域内声明的函数a');}}a();
})();----------------------function a() {console.log('我是全局作用域内声明的函数a');
}
(function () {var a;if (false) {a = function () {console.log('我是块级作用域内声明的函数a');}}a();
})();

为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

🍟2 const声明符

const声明一个只读的常量。一旦声明,常量的值就不能改变。 const与let在 块作用域 重复声明 致死域的问题上是一致的 const的作用域与let命令相同:只在声明所在的块级作用域内有效。

const DATA = '我是常量 不能改变哦';
DATA //  '我是常量 不能改变哦'DATA = '改一个试试看';
// TypeError: Assignment to constant variable.

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

🎲2.1 声明时必须赋值

const X;
//Uncaught SyntaxError: Missing initializer in const declaration

🎲2.2 值为对象

const KEY_MAP = {a:1,b:2
}KEY_MAP['a'] = 2; //不报错-----------const ARRAY = [];
ARRAY.push('something'); // 可执行
ARRAY.length = 0;    // 可执行
ARRAY = ['something'];    // 报错

在这里插入图片描述


💯解构赋值

ES6提供了更简洁的赋值模式, 从数组和对象中提取值. 这被称为解构(Destructuring)。

[a, b] = [50, 100];console.log(a);
// expected output: 50console.log(b);
// expected output: 100[a, b, ...rest] = [10, 20, 30, 40, 50];console.log(rest);
// expected output: [30, 40, 50]

我们有很多种不同的方式使用 JavaScript 解构。

🍟1 数组解构

数组解构是极为简单整洁的,在复制表达式的左侧使用数组字面量。数组字面量中的每个变量名称映射为解构数组的相同索引项。

🎲1.1 基础变量赋值

let foo = ['one', 'two', 'three'];let [red, yellow, green] = foo;
console.log(red); // "one"
console.log(yellow); // "two"
console.log(green); // "three"

🎲1.2 声明分别赋值

你可以通过变量声明分别解构赋值。举例:首先,声明变量,然后分别赋值。

// 声明变量
let a, b;
// 然后分别赋值
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2

🎲1.3 解构默认值

如果解构取出的值是 undefined,可以设置默认值:

let a, b;
// 设置默认值
[a = 5, b = 7] = [1];
console.log(a); // 1
console.log(b); // 7

在上面的例子中,我们给 ab 设置了默认值。这种情况下,如果 ab 的值是 undefined,它将赋值默认值 5a 7b

🎲1.4 交换变量值

解构可以在一个解构表达式中交换两个变量值

let a = 1;
let b = 3;[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

如果你想不使用解构交换变量值,将必须提供一个缓存变量或者同解构一起使用

🎲1.5 解析函数返回的数组

可以解构函数返回的数组。

function c() {return [10, 20];
}let a, b;
[a, b] = c();
console.log(a); // 10
console.log(b); // 20

在上面的例子中,c() 的返回值 [10, 20] 可以在单独的一行代码中使用解构解析。

🎲1.6 忽略返回值/跳过某项

你也可以跳过一些没有用的返回值。

function c() {return [1, 2, 3];
}let [a, , b] = c();
console.log(a); // 1
console.log(b); // 3

在罕见的情况下,你想忽略所有的值。

[, ,] = c();

当然,这是不会发生的。

🎲1.7 赋值数组剩余值给一个变量

当你使用数组解构,你可以赋值数组剩余部分给一个单独的变量。

let [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

小心结尾的逗号语法错误,它将爆发如果在剩余元素的左侧使用结尾逗号:

let [a, ...b,] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma

🎲1.8 嵌套数组解构

像对象一样,你也可以使用数组嵌套解构。这里有一个例子:

const color = ['#FF00FF', [255, 0, 255], 'rgb(255, 0, 255)'];// Use nested destructuring to assign red, green and blue
// 使用嵌套解构赋值 red, green, blue
const [hex, [red, green, blue]] = color;console.log(hex, red, green, blue); // #FF00FF 255 0 255

🍟2 对象解构

🎲2.1 基础对象解构

let x = { y: 22, z: true };
let { y, z } = x; // let {y:y,z:z} = x;的简写console.log(y); // 22
console.log(z); // true

🎲2.2 无声明解构

你可以使用解构分别从它的声明赋值变量。这意味着在上面的例子中不需要创建变量 x

let y, z;({ y, z } = { y: 1, z: 2 });

注意:圆括号 (...) 包裹赋值声明是必须的当使用对象字面量解构赋值无声明变量。

{a, b} = {a: 1, b: 2} 不是有效的独立语法,左侧的 {a, b} 被考虑为代码块而不是一个对象字面量。

因此,({a, b} = {a: 1, b: 2}) 是有效的, 等价于 var {a, b} = {a: 1, b: 2}

(...) 表达式需要前置分号或者它可能用于在前一行执行函数。

🎲2.3 赋值给新变量名

当使用对象解构时你也可以改变变量的名称,如下例子:

let o = { p: 22, q: true };
let { p: foo, q: bar } = o;console.log(foo); // 22
console.log(bar); // true

例子中,var {p: foo} = o 获取对象 o 的属性名 p,然后赋值给一个名称为 foo 的变量。

🎲2.4 解构默认值

如果解构取出的对象值是 undefined 你也可以设置默认值。

let { a = 10, b = 5 } = { a: 3 };console.log(a); // 3
console.log(b); // 5

🎲2.5 赋值给新变量名的同时提供默认值

let { a: aa = 10, b: bb = 5 } = { a: 3 };console.log(aa); // 3
console.log(bb); // 5

🎲2.6 嵌套对象和数组解构

const metadata = {title: 'Scratchpad',translations: [{locale: 'de',localization_tags: [],last_edit: '2014-04-14T08:43:37',url: '/de/docs/Tools/Scratchpad',title: 'JavaScript-Umgebung',},],url: '/en-US/docs/Tools/Scratchpad',
};let {title: englishTitle, // 重命名translations: [{title: localeTitle, // 重命名},],
} = metadata;console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"

🎲2.7 可计算对象属性名与解构

当使用解构改变对象属性的名称时,可以使用对象计算属性名。

let key = 'z';
let { [key]: foo } = { z: 'bar' };console.log(foo); // "bar"

在上面的例子中,我们计算变量键值并改变它的名称为 foo

🎲2.8 同时使用数组和对象解构

在解构中数组和对象可以联合使用:

const props = [{ id: 1, name: 'Fizz' },{ id: 2, name: 'Buzz' },{ id: 3, name: 'FizzBuzz' },
];const [, , { name }] = props;console.log(name); // "FizzBuzz"

所有的解构赋值语法是相同的,是在赋值符号左侧声明从源变量取出的值。举例来说:

let x = [1, 2, 3, 4, 5];
let [y, z] = x;
console.log(y); // 1
console.log(z); // 2

🎲2.9 注意点

(1)如果要将一个已经声明的变量用于解构赋值,必须非常小心。

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

// 正确的写法
let x;
({x} = {x: 1});

上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。

(2)解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。

({} = [true, false]);
({} = 'abc');
({} = []);

上面的表达式虽然毫无意义,但是语法是合法的,可以执行。

(3)由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

上面代码对数组进行对象解构。数组arr0键对应的值是1[arr.length - 1]就是2键,对应的值是3。方括号这种写法,属于“属性名表达式”

🍟3 函数参数的解构赋值

函数的参数也可以使用解构赋值。

function add([x, y]){return x + y;
}add([1, 2]); // 3

上面代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量xy。对于函数内部的代码来说,它们能感受到的参数就是xy

下面是另一个例子。

[[1, 2], [3, 4]].map(([a, b]) => a + b); 
// [ 3, 7 ]

函数参数的解构也可以使用默认值。

function move({x = 0, y = 0} = {}) {return [x, y];
}move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量xy的值。如果解构失败,xy等于默认值。

注意,下面的写法会得到不一样的结果。

function move({x, y} = { x: 0, y: 0 }) {return [x, y];
}move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

上面代码是为函数move的参数指定默认值,而不是为变量xy指定默认值,所以会得到与前一种写法不同的结果。

undefined就会触发函数参数的默认值。

[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]

🍟4 解构的用途

变量的解构赋值用途很多。

🎲4.1 交换变量的值

let x = 1;
let y = 2;[x, y] = [y, x];

上面代码交换变量xy的值,这样的写法不仅简洁,而且易读,语义非常清晰。

🎲4.2 从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

// 返回一个数组function example() {return [1, 2, 3];
}
let [a, b, c] = example();// 返回一个对象function example() {return {foo: 1,bar: 2};
}
let { foo, bar } = example();

🎲4.3 函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来。

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

🎲4.4 提取 JSON 数据

解构赋值对提取 JSON 对象中的数据,尤其有用。

let jsonData = {id: 42,status: "OK",data: [867, 5309]
};let { id, status, data: number } = jsonData;console.log(id, status, number);
// 42, "OK", [867, 5309]

上面代码可以快速提取 JSON 数据的值。

🎲4.5 函数参数的默认值

jQuery.ajax = function (url, {async = true,beforeSend = function () {},cache = true,complete = function () {},crossDomain = false,global = true,// ... more config
} = {}) {// ... do stuff
};

指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';这样的语句。


在这里插入图片描述


JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/329728.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】每日一题 2024_5_24 找出最具竞争力的子序列(栈,模拟,贪心)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;找出最具竞争力的子序列题目描述代码与解题思路 每天进步一点点 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;找出最具竞争力的子序列 题目链接&a…

【Unity2D:C#Script】实现角色射击功能

一、创建子弹预制体 1. 创建子弹预制体 2. 调整图片大小、层级 二、为子弹添加碰撞体积 1. 添加Box Collider 2D、Rigidbody 2D组件 2. 锁定z轴 三、编辑敌人脚本 注&#xff1a;在以下代码中&#xff0c;只显示本章节新增的代码&#xff0c;省略原有的代码 1. 为敌人添加生…

一阶数字高通滤波器

本文的主要内容包含一阶高通滤波器公式的推导和数字算法的实现以及编程和仿真 1 计算公式推导 1.1.2 算法实现及仿真 利用python实现的代码如下&#xff1a; import numpy as np # from scipy.signal import butter, lfilter, freqz import matplotlib.pyplot as plt #2pifW…

免费分享一套微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端Vue管理端) Java毕业设计…

视频监控管理平台LntonCVS监控视频汇聚融合云平台主要功能应用场景介绍

随着网络技术的不断发展和万物互联时代的到来&#xff0c;视频融合在一些系统集成项目及综合管理应用中变得日益重要。本文以LntonCVS视频融合云平台为案例&#xff0c;探讨视频融合的对象及其应用场景。 1. 视频监控设备 视频监控摄像设备是各种视频应用项目的基础部分。在视…

亚马逊卖家账号注册复杂吗?需要什么辅助工具吗?

在当今数字化的商业世界中&#xff0c;亚马逊作为全球最大的电商平台之一&#xff0c;吸引着无数的卖家和买家。对于想要进入亚马逊销售市场的卖家来说&#xff0c;首先要完成的一项重要任务就是注册亚马逊卖家账号。本文将详细介绍亚马逊注册的步骤、所需时间&#xff0c;以及…

入门四认识HTML

一、HTML介绍 1、Web前端三大核心技术 HTML&#xff1a;负责网页的架构 CSS&#xff1a;负责网页的样式、美化 JS&#xff1a;负责网页的行动 2、什么是HTML HTML是用来描述网页的一种语言。 3、Html标签 单标签<html> 双标签<h>内容</h> 4、标…

【译】组复制和 Percona XtraDB 集群: 常见操作概述

原文地址&#xff1a;Group Replication and Percona XtraDB Cluster: Overview of Common Operations 在这篇博文中&#xff0c;我将概述使用 MySQL Group Replication 8.0.19&#xff08;又称 GR&#xff09;和 Percona XtraDB Cluster 8 (PXC)&#xff08;基于 Galera&…

服务器数据恢复—EVA存储多块硬盘离线导致部分LUN丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 1台某品牌EVA4400控制器3台EVA4400扩展柜28块FC硬盘。 服务器故障&#xff1a; 由于两块磁盘掉线导致存储中某些LUN不可用&#xff0c;某些LUN丢失&#xff0c;导致存储崩溃。 服务器数据恢复过程&#xff1a; 1、由于EVA4400存储故障是某些磁…

Java 对外API接口开发 java开发api接口如何编写

Java API API&#xff08;Application Programming Interface&#xff09;是指应用程序编程接口&#xff0c;的JavaAPI是指JDK提供的各种功能的Java类 String类 String类的初始化&#xff1a; &#xff08;1&#xff09;使用字符串常量直接初始化 初始化&#xff1a;String s…

闲话 .NET(4):为什么要跨平台?

前言 .NET Core 有一个关键词就是跨平台&#xff0c;为什么要跨平台呢&#xff1f;Windows 操作系统不香吗&#xff1f;今天我们来聊聊这个 原因一&#xff1a;安全考虑 Windows OS 是闭源的&#xff0c;而 Linux 是开源的&#xff0c;因此有些公司的技术负责人就认为 Linux…

笔记:weblogic配置内存启动参数

可以在控制台配置 参数值 -Xms2048m -Xmx2048m -XX:PermSize512m -XX:MaxPermSize512m -Xss128k激活更改。修改完之后&#xff0c;节点需要重启才能生效。 参数说明&#xff1a; -Xms 为JVM启动时分配的内存 -Xmx 为JVM运行过程中分配的最大内存 -XX:PermSize 为JVM初始分配…

Qt笔记:动态处理多个按钮点击事件以更新UI

问题描述 在开发Qt应用程序时&#xff0c;经常需要处理多个按钮的点击事件&#xff0c;并根据点击的按钮来更新用户界面&#xff08;UI&#xff09;&#xff0c;如下图。例如&#xff0c;你可能有一个包含多个按钮的界面&#xff0c;每个按钮都与一个文本框和一个复选框相关联…

python从0开始学习(十二)

目录 前言 1、字符串的常用操作 2、字符串的格式化 2.1 格式化字符串的详细格式&#xff08;针对format形式&#xff09; ​编辑 总结 前言 上一篇文章我们讲解了两道关于组合数据类型的题目&#xff0c;本篇文章我们将学习新的章节&#xff0c;学习字符串及正则表达式。 …

react实现把pc网站快捷添加到桌面快捷方式

文章目录 1. 需求2. 实现效果3. 核心逻辑4. 完整react代码 1. 需求 这种需求其实在国外一些游戏网站和推广网站中经常会用到&#xff0c;目的是为了让客户 快捷方便的保存网站到桌面 &#xff0c;网站主动尽量避免下次找不到网站地址了&#xff0c;当然精确的客户自己也可以使…

打印安全:防止打印过程中的商业机密泄露

在数字化办公日益普及的今天&#xff0c;打印安全常常成为企业信息保护中被忽视的一环。商业机密在打印过程中泄露&#xff0c;可能会给企业带来巨大的损失。本文将探讨如何通过一系列措施&#xff0c;确保打印过程中的商业机密安全。 一、打印安全的重要性 打印设备作为企业中…

hbase版本从1.2升级到2.1 spark读取hive数据写入hbase 批量写入类不存在问题

在hbase1.2版本中&#xff0c;pom.xml中引入hbase-server1.2…0和hbase-client1.2.0就已经可以有如下图的类。但是在hbase2.1.0版本中增加这两个不行。hbase-server2.1.0中没有mapred包&#xff0c;同时mapreduce下就2个类。版本已经不支持。 <dependency><groupId>…

两步将 CentOS 6.0 原地升级并迁移至 RHEL 7.9

《OpenShift / RHEL / DevSecOps 汇总目录》 说明 本文介绍如何将一个 CentOS 6.0 的系统升级并转换迁移到 RHEL 7.9。 本文是《在离线环境中将 CentOS 7.X 原地升级并迁移至 RHEL 7.9》阶进篇。 所有被测软件的验证操作可参见上述前文中对应章节的说明。 准备 CentOS 6.…

数据量较小的表是否有必要添加索引问题分析

目录 前言一、分析前准备1.1、准备测试表和数据1.2、插入测试数据1.3、测试环境说明 二、具体业务分析2.1、单次查询耗时分析2.2、无索引并发查询服务器CPU占用率分析2.3、添加索引并发查询服务器CPU占用率分析 三、总结 前言 在一次节日活动我们系统访问量到达了平时的两倍&am…

SAP PRD覆盖QAS 替代方案构想

随着时间的推移&#xff0c;SAP PRD的数据跟QAS的差异会越来越大&#xff0c;一般是定期PRD覆盖QAS。但是在没有BASIS的情况下&#xff0c;没有这块经验的情况下&#xff0c;也没有外部支持的情况下&#xff0c;贸然做这个事情也是有风险的&#xff0c;有没有替代方案&#xff…