es6——块级作用域
1.var声明及变量的提升机制
在函数作用域或者全局作用域中通过var声明的变量,都会被当成在当前作用域顶部声明的变量
例:
function getValue(condition) {
if (condition) {
var value = "blue";
return value;
} else {
// 此处可访问变量value,其值为undefined
return null;
}
// 此处可访问变量value,其值为undefined
}
上述相当于:
function getValue(condition) {
var value;
if (condition) {
value = "blue";
return value;
} else {
// 此处可访问变量value,其值为undefined
return null;
}
// 此处可访问变量value,其值为undefined
}
2.块级声明
1)用let和const声明变量,可以把变量的作用域限制在当前代码块(a.函数内部,b.块中(字符{和}之间的区域))中,而且声明的变量不会提升,作用域之外无法访问作用域内定义的变量
例:
function getValue(condition) {
if (condition) {
// 此处为临时死区(Temporal Dead Zone),使用console.log(typeof value)语句会抛出错误。因为JavaScript引擎在扫描代码发现变量声明时,要么将它们提升至作用域顶部(遇到var声明),要么将声明放到TDZ中(遇到let和const声明)。访问TDZ中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从TDZ中移出,然后方可正常访问。
let value = "blue";
return value;
} else {
// 变量value在此处不存在
return null;
}
// 变量value在此处不存在
}
2)禁止重声明:同一作用域中不能用let或者const重复定义已经存在的标示符
例: var count = 30;
// 抛出语法错误
let count = 40;
3)const声明
const声明的是常量,其值一旦被设定后不可更改。因此,每个通过const声明的常量必须进行初始化
例: const maxItems = 30;
const name;// 语法错误:常量未初始化
const声明和let声明有一处很大的不同,即不可以为const定义的常量再赋值,否则会抛出错误;
const声明不允许修改绑定,但允许修改值。即用const声明对象后,可以修改该对象的属性值。
3.循环中的块作用域绑定
var funcs = [ ];
for (let i =0; i< 10;i++){ // 注:此处若用const声明,则会抛出错误。因为在循环的第一个迭代中,i是0,迭代执行成功。然后执行i++,因为这条语句试图修改常量,因此抛出错误。
funcs.push(function() { 所以,如果后续循环不会修改该变量,那可以使用const声明,即在for-in或者for-of循环中使用const时的行为与使用let一样。
console.log(i);
});
}
funcs.forEach(function(func) {
func(); // 输出0,然后是1、2,直到9; 若用var定义变量,则输出10次10
}
4.全局块作用域绑定
当var被用于全局作用域时,它会创建一个新的全局变量作为全局对象(浏览器环境中的window对象)的属性,这意味着使用var和可能会无意中覆盖一个已经存在的全局属性;
而使用let或者const,会在全局作用域下创建一个新的绑定,但该绑定不会添加为全局对象的属性,换句话说,用let或const不能覆盖全局变量,而只能遮蔽它;
var a = 1;
let b = 2;
console.log(a); // 1
console.log(window.a); // 1
console.log(b); // 2
console.log(window.b); // undefind
小结: 当前使用块级绑定的最佳实践是:默认使用const,只在确实需要改变变量的值时使用let。这样就可以在某种程度上实现代码的不可变,从而防止某些错误的产生。