var
如果在函数内部使用 var
声明变量,无论在内部的哪个地方声明,都相当于在函数的第一行声明该变量。若在函数外部使用 var
声明,则相当于在源文件的第一行声明该变量。这种行为称为变量提升 (hoisting)。
块级声明
let
声明的变量和其他类 C 语言一样具有块级作用域,生命周期从声明开始直到所在块结束。
不能在同一个块级作用域内声明同一个标识符两次,否则会抛出错误。
const
声明的变量是常量,与其他类 C 语言一致,具有块级作用域。
const
声明的变量引用对象,则不能修改对该对象的引用,但可以修改该对象的成员。
let
或 const
声明的变量如果在该变量所在的作用域内,声明语句之前使用,会发生运行时错误。但是可以在变量的作用域之外对该变量使用 typeof,不报错,此时变量为未定义。
循环中块级绑定
如果在循环中定义函数,函数用到了循环体内定义的 var
变量,则每个函数中该变量都是同一个,调用每个函数时使用的都是该变量。如
var f = [];
for (var i = 0; i < 10; i++) {
f.push(function () {
console.log(i);
})
}
// 输出 10 个 10
f.forEach(function (func) {
func();
});
为解决这个问题,可以将 var
变量传入函数中,在该函数中定义一个新函数,在新函数中使用该变量,相当于复制了一份该变量的值。如
var f = [];
for (var i = 0; i < 10; i++) {
f.push(function (v) {
return function () {
console.log(v);
};
}(i));
}
// 输出 0 - 9
f.forEach(function (func) {
func();
});
在 for 循环中使用 let
声明的变量,每次迭代时都重新定义并初始化同名的变量。也就是每次迭代使用的变量只有名称一样,实际上是不同的变量。
在 for 循环中使用 const
声明的变量不能改变值,否则抛出错误。可以在 for-in 或 for-of 中使用 const
,此时迭代相当于重新创建了新的常量。
全局块级绑定
var
在全局作用域中声明变量时,在将该变量声明为全局变量的同时也将该变量作为了全局对象的一个属性(浏览器中全局对象为 window)。而 let
和 const
仅声明全局变量,不会将该变量作为全局对象的属性。
参考
[1] Zakas, Understanding ECMAScript 6, 2017.