前言

来自阅读阮老师的《ES6入门》的小结+疑问~先开个坑,慢慢填

问题

Q:let和for循环?
先看书中的一段代码:

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

这个我们知道,是因为每个a[i]都被赋予了一个函数,输出作用域的i,而a[6]()是在全局作用域下调用的,所以输出的i是全局变量i,因为for循环没有块作用域,所以输出10。
改成let后:

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

其实我第一次看到这里是不能理解的,然后看到书上说:

变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。

好吧,还是感觉没清楚到底这个机制是啥样的(⊙﹏⊙),那我就用小工具把它转为ES5语法了(虽然也不能当成完全等同吧(lll¬ω¬)):

"use strict";
var a = [];

var _loop = function _loop(i) {
  a[i] = function () {
    console.log(i);
  };
};

for (var i = 0; i < 10; i++) {
  _loop(i);
}
a[6](); // 6

这个结果就很清楚啦,它类似在执行语句的外面包裹了一个函数,结果就是i当成参数传进去了,而且还形成了一个闭包:
图片描述

再来看另一个例子:

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

原文说:

for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

转换之后的结果(这里有小问题0_0,单纯转换出来会都是i,但是多复制一份,转出来就是下面这种,我个人觉得根据意思应该转成这样才是对的):

for (var _i = 0; _i < 3; _i++) {
  var _i2 = 'abc';
  console.log(_i2);
}

Q:let特性?
不存在变量提升
暂时性死区(temporal dead zone)

在代码块内,使用let命令声明变量之前,该变量都是不可用的

MOCHIKO
318 声望29 粉丝