还是先从一个题目开始:

写一个隔1s输出数组的一项的函数。

如果可以用ES6语法,则可以这么写:

function print (arr) {
for (let i = 0; i < arr.length; i++) {
setTimeout(() => {
console.log(arr[i])
}, 1000 * i);
}
}

但是如果把这里的let改成var,则输出就会变成一连串的undefined

有同学很快想到了这是闭包啊,因为setTimeout把函数加入到microqueue中,所以等到setTimeout的函数体执行时,i已经走完了for循环,变成了arr.lengtharr[arr.length]显然是undefined。

简单修改一下,变成ES5的语法。

function print (arr) {
for (var i = 0; i < arr.length; i++) {
(function (index) {
setTimeout(() => {
console.log(arr[index])
}, 1000 * index);
})(i);
}
}

其实就是利用闭包是向父级作用域寻找值的特性,给i包装一层作用域,把i存起来。

闭包概念还请翻看之前的一篇blog-闭包和类

到这里闭包的理解应该差不多了,而今天的关键点在于——

let做了什么?

阮一峰老师的《ECMAScript 6》入门里给出[定义](http://es6.ruanyifeng.com/#docs/let

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

他提到了let的几个特性:

  1. 只存在于块级作用域中

  2. 不存在变量提升

  3. 暂时性死区

  4. 不允许重复声明

这里我不再赘述,大家可以仔细阅读一下阮一峰老师的书。

我更感兴趣的是,在ES5的语法中,如何模拟let这种块级作用域的效果。这个时候,应该让babel出场了。

打开这个链接:可以看到转换后的代码。

"use strict";

function print(arr) {
var _loop = function _loop(i) {
setTimeout(function () {
console.log(arr[i]);
}, 1000 * i);
}; for (var i = 0; i < arr.length; i++) {
_loop(i);
}
}

其实可以对比发现,babel转换后的代码和我们上面写的ES5实现其实是一样的。

大概就是通过对let绑定的块级作用域加一个函数,把let声明的参数,通过函数传入,达到块级作用域的效果。

大家可以在babel试一下let的其他特性,转移出的ES5语法并不能实现有的特性,比如暂时性死区。

完,感谢阅读。

闭包和let块级作用域的更多相关文章

  1. JavaScript函数表达式、闭包、模仿块级作用域、私有变量

    函数表达式是一种非常有用的技术,使用函数表达式可以无需对函数命名,从而实现动态编程.匿名函数,是一种强大的方式,一下总结了函数表达式的特点: 1.函数表达式不同于函数声明,函数声明要求有名字,但函数表 ...

  2. JS 模仿块级作用域

    function outputNumbers(count) { for (var i=0; i<count; i++) { console.log(i); } var i;  // 重新声明变量 ...

  3. js中的块级作用域

    概述 函数是js中最常见的作用域单元, 声明在一个函数内部的变量或函数会在所处的作用域中隐藏起来, 这是有意为之的非常好的设计原则. 但是随着js的发展, 我们有了某个代码块(通常指{..}内部)隐藏 ...

  4. 你不知道的JS之作用域和闭包(三)函数 vs. 块级作用域

      原文:你不知道的js系列 在第(二)节中提到的,标识符在作用域中声明,这些作用域就像是一个容器,一个嵌套一个,这个嵌套关系是在代码编写时定义的. 那么到底是什么产生了一个新的作用域,只有函数能做到 ...

  5. ES6 浅谈let与const 块级作用域之封闭空间(闭包)

    ES6新增了 let const 命令,用来声明变量.它的用法类似于 var  ,但是所声明的变量,只在 let const 命令所在的代码块内有效.  var const 不允许重复声明 用处: 可 ...

  6. JavaScript模仿块级作用域

    avaScript 没有块级作用域的概念.这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,来看下面的例子: function outputNumbers(count){ for ( ...

  7. ES6之块级作用域

    一.前言 在ECMAScript6(以下简称ES6)之前,ECMAScript的作用域只有两种: 1.  全局作用域: 2.  函数作用域. 正是因为有这两种作用域,所以在JavaScript中出现一 ...

  8. ES6 - Note1:块级作用域与常量

    在ES6以前,ES不支持块级作用域,只有全局作用域和函数作用域,所有变量的声明都存在变量声明提升. 1.let 关键字 声明一个块级变量,只在一个代码块中有效,如果在块外面访问便会报错,如下所示: { ...

  9. JavaScript的作用域和块级作用域概念理解

    作用域 作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期.说到这里我们需要理解两个概念:块级作用域与函数作用域. 函数作用域 这个应该好理解,函数作用域就是说定义在 ...

随机推荐

  1. Python中元组和列表

    一.list列表的操作包括以下函数: 列表操作包括以下函数: 1.cmp(list1,list2) :比较两个列表的元素 2.len(list) :列表元素个数 3.max(list) :返回列表元素 ...

  2. nodejs的get与post

    index.html <html> <body> <form action="/api/v1/records" method="post&q ...

  3. 移动端布局注意事项与less

    用Koala实现less的实时编译 1.下载Koala(Koala可以实现实时编译) 2.把CSS文件夹(如index.css,index.less)拖到Koala中 3.点击到需要编译的index. ...

  4. 【代码笔记】Java常识性基础补充(二)——数组、ArrayList集合、ASCII编码、 eclipse基础操作、eclipse调试、eclipse项目导入、eclipse快捷键

    1.0 如何定义数组以及访问数组中的元素,如下所示.ArrayDemo01.java public class ArrayDemo01 { public static void main(String ...

  5. js数组与字符串处理 slice、splice、substring、substr、push、pop、shift、reverse、sort、join、split

    数组 方法 1.在数组末尾添加.删除元素 push()方法可以接收任意数量的参数,把它们逐个添加到数组的末尾,并返回修改后数组的长度.改变原数组 pop()方法则从数组末尾移除最后一个元素,减少数组的 ...

  6. 按键精灵Q语言基础

    一.数据类型1.1数据类型可以表示一切的类型variant逻辑类型:boolean (true,false)数学类型: 整数:byte(0-255),integer(-32768-32767),lon ...

  7. Android fastjson

    Fastjson介绍 Fastjson是一个Java语言编写的JSON处理器. 1.遵循http://json.org标准,为其官方网站收录的参考实现之一. 2.功能qiang打,支持JDK的各种类型 ...

  8. Python 练习项目1 弹球游戏

    这几天学习了python的基础知识,然后参考了网上的一些资料,完成了一个自己的小游戏,弹球游戏比较简单,但却具备了一些游戏的普遍特征,对于初学者是一个比较合适的锻炼的项目. 下面是效果图: 完整程序: ...

  9. C#性能优化实践(转载)

    原文地址http://www.infoq.com/cn/articles/C-sharp-performance-optimization?utm_source=infoq&utm_mediu ...

  10. python numpy+mkl+scipy win64 安装

    用pip在windows下安装numpy,scipy等库时一般来说都不会很顺利比较好的方式是自己下载对应的whl文件pip install 话不多说上链接 http://www.lfd.uci.edu ...