ES6初探-let与块级作用域
很久没有写博客,日子一天天过得很快,觉得有时候写点东西会让人沉静下来边思考边整理,一直纠结let是个什么东西,看了些面试题好多都关于这个的,今天终觉恍然大悟啊,然后整个人就开心起来了,终究学习还是使人快乐啊!
进入正题吧~~
首先我们说一下块级作用域的定义:任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
/*利用匿名函数表达式可以模拟出块级作用域*/
(function (){
var i = 100;
console.log("block:" + i);
})();
除此之外我们可以用let来实现块级作用域。
ES6 新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
没有块级作用域会带来什么样的麻烦呢?
1.由于ES5只有全局作用域和函数作用域,没有块级作用域,会带来很多问题,比如说向下面的例子,内层变量可能会覆盖外层变量。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
上面代码的原意是,
if
代码块的外部使用外层的tmp
变量,内部使用内层的tmp
变量。但是,函数f
执行后,输出结果为undefined
,原因在于变量提升,导致内层的tmp
变量覆盖了外层的tmp
变量。
2.用来计数的循环变量泄露为全局变量。
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
上面代码中,变量i
只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
let实现块级作用域例子:
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
上面的函数有两个代码块,都声明了变量n
,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var
定义变量n
,最后输出的值就是10。
let声明变量的特点:
1.var
命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined
。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
为了纠正这种现象,let
命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
2.只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
ES6明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
3.let
不允许在相同作用域内,重复声明同一个变量。
/ 报错
function () {
let a = 10;
var a = 1;
}
// 报错
function () {
let a = 10;
let a = 1;
}
以上是学习自阮一峰老师的ECMAScript 6入门,我觉得介绍得非常清楚,适合对初学ECMAScript 6的孩子们。网址:http://es6.ruanyifeng.com/
上一篇: 主板BIOS导致安装系统失败
下一篇: 让老主板不再拒绝新网卡