全局块级绑定
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
。在浏览器中跨越帧或窗口去访问代码时,这种做法非常普遍。