在 ES5 中,咱们一般会使用 var
来声明变量。在使用 var
声明变量的时候,一般会遇到变量声明提高的问题。这种机制会让不少初学者迷惑不解。其实当咱们理解了一个变量一般包括声明和赋值两个部分,这个问题也就不难理解了。编程
// 1
console.log(a); // undefined
var a = 3;
// 2
function foo() {
console.log(b); // undefined
if (true) {
var b = 2;
}
}
复制代码
事实上,不管在全局做用域或者函数做用域中,只要经过 var
关键字声明的变量,不论在哪里声明,都会被当成在当前做用域顶部声明的变量。bash
// 1
var a;
console.log(a);
a = 3;
// 2
function foo() {
var b;
console.log(b);
if (true) {
b = 2;
}
}
复制代码
其实,变量提高的机制,不太符合咱们的编码习惯,咱们经常但愿代码可以按照顺序执行,这也符合通常人的逻辑习惯。为此 ES6 引入了块级做用域的概念。微信
块级做用域其实就是词法做用域,咱们的代码写在哪,就会在哪里执行,这更符合咱们的编程习惯。咱们常说的块包括函数内部 和 {}之间的部分。函数
为了实现块级做用域,ES6 采用 let
和 const
代替 var
来声明变量。用 let
和 const
声明的变量会把变量的做用域限制在当前的代码块中,而且声明的变量不会被提高。另外,用 let
声明的变量,在同一代码块内,禁止重复声明。ui
// 一、变量不会提高
console.log(a); // ReferenceError: a is not defined
let a = 3;
// 二、变量只能在当前做用域访问
if (true) {
const b = 3;
console.log(b); // 3
}
console.log(b); // ReferenceError: b is not defined
// 三、禁止重复声明
function foo() {
let c = 3;
let c = 4; // Identifier 'c' has already been declared
}
foo();
复制代码
用 let
和 const
均可以建立一个块级做用域,惟一的区别是 const
用来声明一个常量,它的值一旦被设定后不可修改。因此,用 const
声明的常量必须初始化。编码
// 一、不可更改
const a = 1;
a = 2; // TypeError: Assignment to constant variable.
// 二、必须初始化
const b; // SyntaxError: Missing initializer in const declaration
复制代码
关于 const
声明的变量不可修改,有一个值得注意的地方就是用 const
声明一个对象。好比:spa
const tom = {
age: 18,
city: 'shanghai'
};
tom.age = 19; // 这是能够的
复制代码
咱们能够理解为,用 const
声明了一个变量 tom,将一个对象的引用地址赋值给变量 tom,只要这个引用地址不发生变化,内部的值是能够修改的。code
在 ES5 中,比较让人头疼的地方可能就是 for 循环了。在循环中,咱们用 var
声明一个变量,循环结束后,咱们实际上是但愿这个变量被销毁的。但因为 var
声明的变量具备声明提高的特性,因此当咱们用 for 循环的时候,每每会污染咱们的全局做用域。cdn
for (var i = 0; i < 10; i++) {
// do something
}
console.log(i); // 10
// 当循环结束的时候,其实咱们是但愿变量 i 能够被销毁的。
// 但其实它被留在了全局
复制代码
这个时候,咱们使用 let
来声明循环中的变量,就能够轻易的解决这个问题。对象
for (let i = 0; i < 10; i++) {
// do something
}
console.log(i); // ReferenceError: i is not defined
// 能够看到,循环结束,变量 i 就被销毁了。 perfect~~
复制代码
最后总结一下,let
和 const
帮助咱们解决了很多问题,咱们不会再为变量提高引起的种种问题而困惑了,同时在循环中使用 let
来代替 var
能够在循环结束的时候销毁变量,避免无用的变量影响全局。而当前使用块级绑定的最佳实践是:默认使用 const
,只在肯定须要改变变量的值时,使用 let
,以最大化地避免错误的产生。
若是文章中有错误或表述不严谨的地方,欢迎指正。
也欢迎你们关注个人同名微信公众号:李等等扣丁