var 声明与提升
使用 var 关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于所在函数的顶部(如果声明不在任意函数内,则视为在全局作用域的顶部)。这就是所谓的变量提升(hoisting )
块级声明
块级声明也就是让所声明的变量在指定块的作用域外无法被访问。块级作用域(又被称为词
法作用域)在如下情况被创建:
- 在一个函数内部
- 在一个代码块(由一对花括号包裹)内部
1、let 声明
语法与var一致,但用let声明的变量会将变量的作用域限制在当前代码中。
特点:
- 无法变量提升
- 禁止重复声明
- 声明前无法访问
2、常量声明
使用 const 声明的变量会被认为是常量(constant ),意味着它们的值在被设置完成后就不能再被改变。
- 常量声明与 let 声明一样,都是块级声明;
- 声明无法提升,声明前无法访问;
- 变量设置完无法修改;
- const声明对象:const 声明会阻止对于变量绑定与变量自身值的修改,这意味着 const 声明并不会阻止对变量成员的修改。
const person = {
name: "Nicholas"
};
// 工作正常
person.name = "Greg";
// 抛出错误
person = {
name: "Greg"
};
块级绑定
1、独特表现
(1)暂时性死区(temporal dead zone)
let 或 const 声明的变量为何在声明处之前无法被访问。
当 JS 引擎检视接下来的代码块并发现变量声明时,它会在面对 var 的情况下将声明提升到
函数或全局作用域的顶部,而面对 let 或 const 时会将声明放在暂时性死区内。任何在暂
时性死区内访问变量的企图都会导致“运行时”错误(runtime error)。只有执行到变量的声明
语句时,该变量才会从暂时性死区内被移除并可以安全使用。
使用 let 或 const 声明的变量,若试图在定义位置之前使用它,无论如何都不能避免暂时
性死区。
(2)循环中使用块级绑定
在 for 循环内,也就是想让一次性的循环计数器仅能在循环内部使用。
for (let i = 0; i < 10; i++) {
process(items[i]);
}
// i 在此处不可访问,抛出错误
console.log(i);
2、全局块级绑定
let 与 const 不同于 var 的另一个方面是在全局作用域上的表现。当在全局作用域上使
用 var 时,它会创建一个新的全局变量,并成为全局对象(在浏览器中是 window )的一
个属性。这意味着使用 var 可能会无意覆盖一个已有的全局属性,就像这样:
// 在浏览器中
var RegExp = "Hello!";
console.log(window.RegExp); // "Hello!"
var ncz = "Hi!";
console.log(window.ncz); // "Hi!"
尽管全局的 RegExp 是定义在 window 上的,它仍然不能防止被 var 重写。
然而若你在全局作用域上使用 let 或 const ,虽然在全局作用域上会创建新的绑定,但不
会有任何属性被添加到全局对象上。这也就意味着你不能使用 let 或 const 来覆盖一个全
局变量,你只能将其屏蔽。
// 在浏览器中
let RegExp = "Hello!";
console.log(RegExp); // "Hello!"
console.log(window.RegExp === RegExp); // false
const ncz = "Hi!";
console.log(ncz); // "Hi!"
console.log("ncz" in window); // false