近几年来javascript发展迅速,从一个浏览器的执行语言慢慢发展为一个服务端语言,现在形成了一个生态圈,工作需要,开始要用到了javascript/node了,从这篇文章开始介绍一些javascript在ES6的新特性。本章讲解一下ES6里新增的let的特性。
基本用法
let和var一样是用来声明变量,只是let声明的变量只有在自己所在的代码块(作用域)里才能使用,当然包括子块:
'use strict';
{
let a = 1;
var b = 2;
console.log(a);//1
console.log(b);//2
}
console.log(a);//ReferenceError: a is not defined
console.log(b);//2
笔者觉得let的主要用户就是在循环中,把需要的变量声明为let型,避免污染下面的变量,或者避免误使用这个变量。但是要注意的是let声明的只在循环体内生效,就不生效了,我们看个例子:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
这个地方,我们打印出来的是10,那我们用let声明看下:
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
用var什么的i打印出来是10,用let声明的打印出来的是6,因为var声明的变量就会在整个函数的生存期可用,而let声明的只在变量所在的代码块中可用。
另一个问题,既然let声明的变量,在跳出代码块之后调用为什么没有报错呢?笔者的理解是let声明的变量i,在代码执行过程中,都会被替换为当时的值,不会再是一个变量,所以在最后调用的时候打印出来是个真实的值,而不会再根据一个变量查找到它的值。
不提前赋值
我们知道,js代码在执行之前会先扫描一遍,先给每个变量赋值为undefined,等到真正赋值的时候再赋值,比如:
console.log(a);//ReferenceError: a is not defined
但是:
console.log(a);//undefined
var a= 1;
那么let呢,我们举个例子:
console.log(foo); // undefined
console.log(bar); // ReferenceError: bar is not defined
var foo = 2;
let bar = 2;
上面的代码在代码执行前,编译器扫描时会将foo提前赋值为undefined,但是let不会,提前使用的时候就会报错了。
暂时性死区
这个怎么说呢,可以这样理解,如果一个作用域里存在let声明的变量,那么这个变量就绑定在这个区域里了,不会再受外部的干扰,即使在它外部,并且在它之前定义了一个命名相同的变量:
var tmp = 123;
if (true) {
tmp = 'abc'; //ReferenceError: tmp is not defined
let tmp = 1;
}
ES6规定暂时性死区和不存在变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在ES5是很常见的,现在有了这种规定,避免此类错误就很容易了。
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
不能重复声明
let不允许在同一个作用域中,重复声明定义一个变量:
if (true) {
let tmp = 'abc';
let tmp = 1;// SyntaxError: Identifier 'tmp' has already been declared
}