同步发布于:https://mingjiezhang.github.io/(转载请说明此出处)。

ES6中加入了let,也让JavaScript拥有了块级作用域。

没有块级作用域的JavaScript

在ES5及其之前的版本里,作用域只有全局作用域和函数作用域两种,而不像其他许多语言一样还拥有块级作用域。没有块级作用域的JavaScript在使用的过程中出现了许多意想不到的具体问题,比如下面这段代码的demo:

var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function () {
console.log(i);
};
}
arr[3]();

如果是学过C++或者其他有块级作用域的人,可能类比觉得上述代码会输出3,不过事实上该代码输出的是10。

因为ES5及之前是没有块级作用域的,i所处的仍是全局作用域而不是块级作用域。因此,循环过程中数组arr的每个数组项所引用的函数中的变量i都是引用全局作用域中的i,因此arr3中i为for循环结束时的i的值10。

对于该问题,有很多方法解决。比如可以将for循环体的代码放入一个立即执行函数中,相当于创建一个新的作用域,将i当做实参传入里及执行函数,本质上是创造了一个模拟的块级作用域,当然也可以认为为内部的函数创建一个闭包(闭包的本质和作用域链息息相关)。

let的出现

现在我们再写之前的那段代码是,有了更加简洁的方法,使用ES6的let。

var arr = [];
for (let i = 0; i < 10; i++) {
arr[i] = function () {
console.log(i);
};
}
arr[3](); //3

let的出现使得JavaScript终于拥有了块级作用域。因为ES6要考虑之前版本的兼容,所以是通过声明let来使用块级作用域。

当我们在一个代码块中使用let来声明变量,通过let声明的变量只在当前块作用域中有效。

{
let a = 1;
var b = 2;
}
console.log(a); //ReferenceError
console.log(b); //2

如上,let的声明方式让let所在的块成为块级作用域,同时let声明的变量无法在全局作用域中访问到,但是var变量依旧可以在全局作用域访问到。

无变量提升

let中不存在变量提升的现象。变量在使用之前必须被声明。

因此,这个定义也导致了暂时性死区的现象。

var c = 'test';
if (true) {
c = 'new'; //ReferenceError
let c;
console.log(c);
}

如上在块级块级作用域中重新声明全局作用域中的c时,这时,编译器会屏蔽全局作用域中的c,在该块级作用域中只能使用新声明的c。但由于块级作用域中let声明的变量无作用域提升现象,因此无法在声明c之前使用c(包括赋值c),出现暂时性死区的现象。

块级作用域

let的出现让JavaScript可以充分利用块级作用域的特性。我们可以在不同的块级作用域中使用同名变量。

if (true) {
let a = 1;
if(true){
let a = 2;
console.log(a); //2
}
console.log(a); //1
}

由于块级作用域出现,我们可以实现上述变量隔离的效果。

总结

let在不影响var使用的情况下,开创了JavaScript的块级作用域,未来想必let也会大量取代var的使用。

欢迎指正交流。未经允许,请勿转载。

ECMAScript 6学习笔记(二):let和块级作用域的更多相关文章

  1. ES6学习笔记(1)- 块级作用域

    1. var声明变量和变量提升(Hoisting)机制的问题 在JS中通过var关键字声明的变量,无论在函数作用域中亦或是全局作用域中,都会被当成当前作用域顶部的变量,和就是所谓的提升机制(Hoist ...

  2. CSS学习笔记——盒模型,块级元素和行内元素的区别和特性

    今天本来打算根据自己的计划进行前端自动化的学习的,无奈早上接到一个任务需求需要新增一个页面.自从因为工作需要转前端之后,自己的主要注意力几 乎都放在JavaScript上面了,对CSS和HTML这方面 ...

  3. ECMAScript 6 学习笔记(二)

    ECMAScript 6 let和const命令 let命令 基本用法 ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a ...

  4. ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring

    接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...

  5. python3.4学习笔记(二) 类型判断,异常处理,终止程序

    python3.4学习笔记(二) 类型判断,异常处理,终止程序,实例代码: #idle中按F5可以运行代码 #引入外部模块 import xxx #random模块,randint(开始数,结束数) ...

  6. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  7. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  8. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  9. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

随机推荐

  1. 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索

    第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...

  2. windbg加载sos.dll

    SOS.dll 中提供的 Son of Strike 扩展 (SOS),用于调试 WinDbg 中的托管代码.在启动了调试程序并将其附加到托管进程(或加载故障转储) .load C:\Windows\ ...

  3. Fiddler捕捉ASP.NET WebSite调用WebService、WCF服务

    Fiddler默认会注册一个代理,有时会发现WebSite调用的WebService或者WCF服务无法被捕捉到.其实是由于运行的站点关联的应用程序池使用的账号和我们当前登陆操作系统的用户不同,自然它们 ...

  4. 字符集与Mysql字符集处理(二)

    接着上篇文章继续讲字符集的故事.这一篇文章主要讲MYSQL的各个字符集设置,关于基础理论部分,参考于这里.   1. MYSQL的系统变量 – character_set_server:默认的内部操作 ...

  5. 使用 IntelliJ IDEA 2016和Maven创建Java Web项目的详细步骤及相关问题解决办法

    Maven简介 相对于传统的项目,Maven 下管理和构建的项目真的非常好用和简单,所以这里也强调下,尽量使用此类工具进行项目构建, 它可以管理项目的整个生命周期. 可以通过其命令做所有相关的工作,其 ...

  6. 自定义能够for each的类,C#,Java,C++,C++/cli的实现方法

    自定义类能够被for each,应该算是个老生常谈的话题了,相关的资料都很多,不过这里整理总结主流语言的不同实现方式,并比较部分细节上的差异. 第一种语言,也是实现起来最简单的Java语言.在Java ...

  7. python异常处理(基础)

    之前在学习python的时候有整理过python异常处理的文章,不够简单也不够完整,所以决定再整理一篇,算做补充. http://www.cnblogs.com/fnng/archive/2013/0 ...

  8. [git]git add 增加文件,文件名乱码

    使用git add添加要提交的文件的时候,如果文件名是中文,会显示形如 274\232\350\256\256\346\200\273\347\273\223.png 的乱码. 解决方案: 在bash ...

  9. 鼠标经过(hover)事件的延时处理

    关于鼠标hover事件及延时 鼠标经过事件为web页面上最常见的事件之一.简单的hover可以用CSS :hover伪类实现,复杂点的用js. 一般情况下,我们是不对鼠标hover事件进行延时处理.但 ...

  10. doctrine2到底是个什么玩意

    之前和最近一个项目用到了Doctrine,由于是别人搭建的,自己没有很了解,最近又开始做的时候发现拙荆见肘,于是看了一下doctrine教程,本文就是加上自己理解的doctrine教程文档笔记了. D ...