全局块级绑定
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重写。这个例子声明 了一个新的全局变RegExp而覆盖了原有对象。类似的,ncz定义为全局变量后就立即成为了window的一个属性。这就是JS通常的工作方式。
然而若你在全局作用域上使用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
此代码的let声明创建了RegExp的一个绑定,并屏蔽了全局的RegExp。这表示window.RegExp与RegExp是不同的,因此全局作用域没有被污染。同样,const声明创建了ncz的一个绑定,但并未在全局对象上创建属性。当你不想在全局对象上创建属性时,这种特性会让let与const在全局作用域中更安全。
若想让代码能从全局对象中被访问,你仍然需要使用
var。在浏览器中跨越帧或窗口去访问代码时,这种做法非常普遍。