在ES6中新加了快作用域的概念(C语言就有,作为类c语言的js,当然应该加上),算是很好理解。

{
let i;
}
console.log(i);// i is not defined

在代码块当中使用新的作用域。

问题在于for语句

let arr=[];
for(let i=0;i<5;i++){
arr[i]=function(){
console.log(i);
};
}

许多的讲解并没有特别说明它的作用域是怎么看的,似乎是自然而然的事情。

然而对于以前c没专心学,真正会的也就类似PHP,javascript的无块作用域的孩子就觉得疑惑了。

我的错误理解1:

let arr = [];
(function(){//作用域直接包含整个for循环?wrong
for (var i = 0; i < 5; i++) {
arr[i] = function () {
console.log(i);
};
}
})();

我的错误理解2:

let arr = [];
for (var i = 0; i < 5; i++) {
(function () {//作用域包含单次循环?wrong
arr[i] = function () {
console.log(i);
};
})();
}

测试结果都说明自己的理解是有误的,找资料的时候,这里都一笔被带过了(可能因为各位作者都用过块作用域的吧)。

于是想到babel既然是ES6转ES5,理解是正确的,那么可以找它帮忙。

方法,使用babel转码加深特性的理解,

直接在线转码

转码前:

let arr=[];
for(let i=0;i<5;i++){
arr[i]=function(){
console.log(i);
};
i++;
}
console.log(i);//i is undefined
arr[0]();

转码后:

"use strict";

var arr = [];

var _loop = function _loop(_i2) {
arr[_i2] = function () {
console.log(_i2);
};
_i2++;
_i = _i2;
}; for (var _i = 0; _i < 5; _i++) {
_loop(_i);
}
console.log(i); //i is undefined
arr[0]();

通过babel转码后就可以清晰的看出来了:

1、作用域是分成两部分的,在整个for循环外层相当于有一个作用域,这里babel使用变量  _i  来区别   i  变量,等价于一个作用域,在理解上可以这样理解,

let arr = [];
for (let i = 0, len = 5; i < 5; i++) {
arr[i] = function () {
console.log(i);
};
}
console.log(i);
arr[0](); "use strict"; var arr = []; var _loop = function _loop(_i) {
arr[_i] = function () {
console.log(_i);
};
};
(function () {
for (var i = 0; i < 5; i++) {
_loop(i);
}
})();
console.log(i); //i is undefined
arr[0](); "use strict"; var arr = []; (function () {//等价于for循环外层作用域,babel中使用变量别名来优化
var _loop = function _loop(_i2) {
arr[_i2] = function () {
console.log(_i2);
};
_i2++;
i = _i2;
}; for (var i = 0; i < 5; i++) {
_loop(i);
}
})();
console.log(i); //i is undefined
arr[0]();

2、每个单次循环也是一个作用域,代码中的_loop,即是用函数作用域来模拟块作用域。

3、在单次循环中注入了for语句中声明的i变量,并且在一次循环后,将i变量赋值回来(_loop代码中i=_i2)。

运行结果是一样,但是却觉得我的理解很有问题,通常越强大的规则通常是越简单的,是否有更准确的解释呢?求不吝相告

ES6中块作用域之于for语句是怎样的?的更多相关文章

  1. ES6 学习笔记之一 块作用域与let和const

    ---恢复内容开始--- 在学习ES6的块作用域和 let.const 之前,我们先来看看ES5以前的 var 关键字. var 关键字用于定义一个变量,通常我们会将其与变量的赋值合并为一条语句,就像 ...

  2. ES6 学习笔记之二 块作用域与闭包

    "闭包是函数和声明该函数的词法环境的组合." 这是MDN上对闭包的定义. <JavaScript高级程序设计>中则是这样定义的:闭包是指有权访问另一个函数作用域中的变量 ...

  3. ES6 中 let 和 const 总结

    目录 let const 1. let要好好用 1. 基本用法 2. let声明的变量不存在变量提升 3. TDZ(temporal dead zone)暂时性死区 4. 不允许重复声明 2. 块级作 ...

  4. ES6中let和闭包

    在开始本文之前我们先来看一段代码 for(var i=0;i<10;i++){ arr[i]=function(){ return i; } } console.log(arr[3]());// ...

  5. ES6(块级作用域)

    我们都知道在javascript里是没有块级作用域的,而ES6添加了块级作用域,块级作用域能带来什么好处呢?为什么会添加这个功能呢?那就得了解ES5没有块级作用域时出现了哪些问题. ES5在没有块级作 ...

  6. ES6之块级作用域

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

  7. Javascript中的词法作用域、动态作用域、函数作用域和块作用域(四)

    一.js中的词法作用域和动态作用域      词法作用域也就是在词法阶段定义的作用域,也就是说词法作用域在代码书写时就已经确定了.       js中其实只有词法作用域,并没有动态作用域,this的执 ...

  8. Java 中 try、catch、finally 语句块的执行顺序

    假设代码顺序书写如下:try → catch → finally → 其他代码 则: 1.正常执行顺序:try → catch → finally → 其他代码 2.try,catch和finally ...

  9. 理解JavaScript中的作用域和上下文

    JavaScript对于作用域(Scope)和上下文(Context)的实现是这门语言的一个非常独到的地方,部分归功于其独特的灵活性. 函数可以接收不同的的上下文和作用域.这些概念为JavaScrip ...

随机推荐

  1. s5pv210 cpu运行debian

    1.环境准备 sudo apt-get install binfmt-support qemu qemu-user-static debootstrap 2.获取debian根文件系统 2.1.cd ...

  2. ECharts-图表回执组件

    测试地址:http://echarts.baidu.com/doc/example.html

  3. fonts.googleapis.com 加载慢的解决方法

    把:fonts.googleapis.com 替换成 fonts.useso.com

  4. 详解 $_SERVER 函数中QUERY_STRING和REQUEST_URI区别(转)

    对于php$_SERVER这个全局变量 ,里面有很多的参数,慢慢的熟悉 1,http://localhost/aaa/ (打开aaa中的index.php)结果:$_SERVER['QUERY_STR ...

  5. (原创)RS232串口信号定义

    好久没用动硬件了,串口更是好久没用用了. 曾经接口信号记得很清楚,久了,忘了. 今天,重新回顾,笔记记下. DB9接口分公头和母头,公头即插针头,电脑机箱上多少公头.母头即插孔座. 合理的硬件设计均以 ...

  6. laravel select 传参

    传值: $params['select'] = 'taobao_id,title,image,price,coupon_deduct,coupon_condition'; 接受参数 $result = ...

  7. 比较评测epoll,select,and poll 时间机制

    https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE21815

  8. 日常积累之JSON.stringify和JSON.parse substr

    1.substr(start,len) 从字符串中读取内容,第一个参数是读取的首位置,如果为负数,则从末尾倒数计数. 第二个参数是要读取的长度. eg: var str = "silence ...

  9. 4.AE中的缩放,书签

    1.书签 private void textBox1_TextChanged(object sender, EventArgs e) { if (txtBookmark.Text == "& ...

  10. 封装properties从配置文件读取测试用例输入数据

    当每个测试用例都有输入数据,而且数据量比较大的情况,可以采取从文件读取 如果想让同一套测试用例能够适应相似的输入数据,如果直接代码里面来回切换回可能会漏,而且还需要debug检错 可以把一些公用的输入 ...