1、let命令
首先let、const命令是在es6中引入的,let用法与var类似,用于声明一个变量,但是使用let声明的变量具有块级作用域(啥叫块级作用域?本文会讲到),而用var声明的变量则是全局变量;const与let一样是具有块级作用域的,但是使用const声明的变量的值不可再被改变,而且必须在声明时赋值。
先给大家来一个常见的例子:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a.forEach((key, val) => {
a[val]();
})
可能一些基础知识比较薄弱的同学就可能会觉得控制台输出的结果是从0到9,但是结果是输出了10个10。
那这究竟是为什么呢?
因为用var声明的变量会成为全局变量,在每次定义的a[i]函数中,仅仅是定义了输出一个i 的命令,但是需要明确的是,i的值是多少取决于执行该函数时i的取值。当在循环外执行a[i]的函数时,内部引擎就会去相对应的作用域寻找i的值,直到最后在全局作用域下找到了全局变量i,此时i的值为10。
很多同学可能会问,假如我想输出的是1、2、3…、9怎么办?这时候let就派上用场了。
我们把代码修改为:
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a.forEach((key, val) => {
a[val]();
})
这就达到了我们所想到达到的目的,但是为什么let会有如此神奇的功能呢?
这是因为let声明的变量具有块级作用域,当for循环中i为0时,不管其他作用域中i的值为多少,函数a[0]只作用在i为0的作用域下,所以执行函数的时候,内部引擎就会先去相对应的作用域中一层一层往上寻找i的值。
变量提升
直接上代码:
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
上述情况中,表明var存在变量提升,而let声明的变量不存在变量提升。
上述的代码在执行过程中会变成:
// var 的情况
var foo;
console.log(foo); // 输出undefined
foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
let部分没有变化,而var声明的变量被提前到代码执行的开头部分,这就是所谓的变量提升,由于使用var声明了foo,在打印输出的时候foo还为赋值,所以值为undefined;而let不存在变量提升,所以直接打印输出bar会报错,因为在console.log(bar);代码上方并未有bar变量的声明。
暂时性死区
let存在暂时性死区,如果在当前块级作用域下使用let 声明a变量,那么内部引擎将不会向上一层作用域搜索a变量的值,具体说明代码如下:
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
首先在全局作用域下使用var声明了tmp变量的值为123,在if的块级作用域中,尝试把全局作用域下的全局变量tmp修改为’abc‘,但是却报错了,原因很简单。因为在if块级作用域中,存在了let声明 tmp变量的语句,该语句直接限制了内部引擎if块级作用域外寻找tmp变量,当执行tmp = 'abc’语句时,由于在该语句前面没有找到对tmp的声明,所以直接报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)
块级作用域
个人看法就是一个{}代表一个块级作用域,不同块级作用域中使用let、const声明相同变量名的变量的值是相互不影响的,仅在各自的块级作用域中生效。
2、const命令
基本用法
const命令是es6中引入的,const声明的变量必须在声明时就赋值不然会报错,const声明的变量的值不可再改变,例子如下:
const a;
console.log(a);// Uncaught SyntaxError: Missing initializer in const declaration
const b = 10;
b = 20; //Uncaught TypeError: Assignment to constant variable.
const具有块级作用域,在块级作用域外无法访问const声明的变量,例子如下:
if (true) {
const a = 10;
}
console.log(a); // Uncaught ReferenceError: a is not defined
使用const声明的变量与使用let声明的变量一样存在暂时性死区,同时也不存在变量提升,例子如下:
const a = 20;
if (true) {
console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
const a = 10;
}
补充:let与const不可在同一块级作用域中多次声明,例子如下:
if (true) {
const a = 10;
const a = 20; // Uncaught SyntaxError: Identifier 'a' has already been declared
let b = 100;
let b = 200; // Uncaught SyntaxError: Identifier 'b' has already been declared
}
如有不对之处,请多多指教!!