闭包和let块级作用域
还是先从一个题目开始:
写一个隔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.length。arr[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的几个特性:
只存在于块级作用域中
不存在变量提升
暂时性死区
不允许重复声明
这里我不再赘述,大家可以仔细阅读一下阮一峰老师的书。
我更感兴趣的是,在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块级作用域的更多相关文章
- JavaScript函数表达式、闭包、模仿块级作用域、私有变量
函数表达式是一种非常有用的技术,使用函数表达式可以无需对函数命名,从而实现动态编程.匿名函数,是一种强大的方式,一下总结了函数表达式的特点: 1.函数表达式不同于函数声明,函数声明要求有名字,但函数表 ...
- JS 模仿块级作用域
function outputNumbers(count) { for (var i=0; i<count; i++) { console.log(i); } var i; // 重新声明变量 ...
- js中的块级作用域
概述 函数是js中最常见的作用域单元, 声明在一个函数内部的变量或函数会在所处的作用域中隐藏起来, 这是有意为之的非常好的设计原则. 但是随着js的发展, 我们有了某个代码块(通常指{..}内部)隐藏 ...
- 你不知道的JS之作用域和闭包(三)函数 vs. 块级作用域
原文:你不知道的js系列 在第(二)节中提到的,标识符在作用域中声明,这些作用域就像是一个容器,一个嵌套一个,这个嵌套关系是在代码编写时定义的. 那么到底是什么产生了一个新的作用域,只有函数能做到 ...
- ES6 浅谈let与const 块级作用域之封闭空间(闭包)
ES6新增了 let const 命令,用来声明变量.它的用法类似于 var ,但是所声明的变量,只在 let const 命令所在的代码块内有效. var const 不允许重复声明 用处: 可 ...
- JavaScript模仿块级作用域
avaScript 没有块级作用域的概念.这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,来看下面的例子: function outputNumbers(count){ for ( ...
- ES6之块级作用域
一.前言 在ECMAScript6(以下简称ES6)之前,ECMAScript的作用域只有两种: 1. 全局作用域: 2. 函数作用域. 正是因为有这两种作用域,所以在JavaScript中出现一 ...
- ES6 - Note1:块级作用域与常量
在ES6以前,ES不支持块级作用域,只有全局作用域和函数作用域,所有变量的声明都存在变量声明提升. 1.let 关键字 声明一个块级变量,只在一个代码块中有效,如果在块外面访问便会报错,如下所示: { ...
- JavaScript的作用域和块级作用域概念理解
作用域 作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期.说到这里我们需要理解两个概念:块级作用域与函数作用域. 函数作用域 这个应该好理解,函数作用域就是说定义在 ...
随机推荐
- rocketmq 两个线程同时消费一个消息
1.问题描述 线上项目A部署两台机器,每台机器两个实例,订阅同一个topic,消费心跳数据. (两台机器host1,host2) 运维同事 部署时 有一个实例用root账户重启的, 然后该实例出现两个 ...
- 初识 ElasticSearch
场景:最近有同事分享了ElasticSearch Inverted Index,所以自己也了解一下基于Lucene的ES. 转载自:http://www.jianshu.com/p/05cff7175 ...
- 01_Jdk自带SPI
[SPI的设计目标] 面向对象的设计里,模块之间是基于接口编程,模块之间不对实现类进行硬编码. 一旦代码里设计具体的实现类,就违法了可插拔的原则,如果需要替代一种实现,就要修改代码. 为了实现在模块装 ...
- 消息循环中的TranslateMessage函数和DispatchMessage函数,特别注意WM_TIMER消息
原文:http://www.cnblogs.com/xingrun/p/3583357.html TranslateMessage函数 函数功能描述:将虚拟键消息转换为字符消息.字符消息被送到调用线程 ...
- mongo 聚合函数
一: 聚合 常见的聚合操作跟sql server一样,有:count,distinct,group,mapReduce. <1> count count是最简单,最容易,也是最常用的聚合工 ...
- 【深入理解JAVA虚拟机】第4部分.程序编译与代码优化.1.编译期优化。这章编译和实战部分没理解通,以后再看。
1.概述 1.1.编译器的分类 前端编译器:Sun的Javac. Eclipse JDT中的增量式编译器(ECJ)[1]. 把*.java文件转变成*.class文件 JIT编译器:HotSpot ...
- Dom4j的一个小例子,用于解析xml文件的元素获取方式
import java.io.File; import java.io.IOException; import javax.xml.parsers.ParserConfigurationExcepti ...
- pycharm 2016注册码
43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...
- [转]删除MSSQL所有的约束及表格
--删除所有约束.表.视图等SQL脚本 --############################################### --删除所有外键约束 --################# ...
- 练习:HPH 数据
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...