还是先从一个题目开始:

写一个隔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. maven配置环境

    今天初学maven,先学习一下如何在windows下面配置maven,当然你要先配置好jdk的环境. 第一步,上官网下载maven插件,网址是:点击打开链接 第二步,解压文件夹,放在某一个盘符下,我是 ...

  2. svn怎么下载代码到本地

    1. 在我们安装好svn时,在指定的目录中点击鼠标右键SVN Checkout,弹出以下窗口.(在文件夹下各自建好前后台的文件夹分别check) 2. 在URL of repository:(存储库的 ...

  3. 移动web开发都会遇到的坑(会持续更新)

    1.自适应第一招 <meta name="viewport" content="width=device-width,initial-scale=1.0,user- ...

  4. 解决Win7远程连接灰色无法选中的问题

    内网开发最常用的莫过于Windows的远程连接服务了.但是有时候这个远程连接是灰色的,无法勾选.折腾了各种办法.最后在这里找到了答案.https://answers.microsoft.com/en- ...

  5. javascript多浏览器的兼容

    一.document.formName.item(”itemName”) 问题 问题说明:IE下,可以使用 document.formName.item(”itemName”) 或 document. ...

  6. css 样式表集合

    说到前端不得不说一下css样式 css样式是用来装饰我们的html让整个页面显得更丰富多彩,所以我们要熟悉各种css样式,本人搜集了一下 供大家参考一下 字体属性:(font) 大小 {font-si ...

  7. cnpm 安装

    国内npm 安装比较慢,可选择cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org

  8. 07_zookeeper的客户端工具curator_基本api

    [zk原生api的不足之处] * 不能自动超时重连,需要手动操作 * watcher事件注册一次后就会失效 * 不支持递归创建节点 [ Apache curator ] * 解决了watcher的注册 ...

  9. JAVA程序编写入门

    在任意文件夹下创建一个文本,然后重命名,把文本后缀名改为.java.然后用eclipse打开此文件编写程序内容. public class nihao{ public static void main ...

  10. ES6入门——变量的解构赋值

    1.数组的解构赋值 以前为变量复制,只能直接指定值.现在ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 本质上,这种写法属于模式匹配,只要等 ...