在ES6 的规范中,多了两个声明变量的关键字: let 和const。初次学习的时候,只记住了 let 声明的变量只在for 的循环体中有效,循环结束后 变量就消失了, 同时const 也能够在for 循环中声明变量,可是不能用于 常规的for 循环中。所谓的常规for 循环就是for(let i =0; i < 10; i++) 的格式。今天重读了一遍Understanding ECMAScript 6, 算是明白了。json
当咱们在使用for 循环的时候,每一次的迭代都会从新声明一个变量。像for(let i = 0; i < 10; i++); 这样使用时,i 变量声明了10次,只不过每一次迭代改i 赋值不同而已,而且变量只在循环体中使用。 咱们能够这样理解: 第一次迭代的使用,声明了一个变量i, 赋值为0, 0 < 10, 而后执行循环体,执行完以后i++ 变成了1. 这一次迭代就结束了,这个i 的使命就完成了。而后进行第二次迭代,这时从新声明一个变量i, 不过此次给他赋值为1,1 < 10 继续执行循环体,而后加1. 此次迭代又结束了,这个i 也完成了使命,消失了。第三次迭代进行一样的操做,声明一个全新的变量i,执行循环体之类的,直达整个循环结束。数组
对于for 循环来讲,每一次的迭代都是从新声明一个全新的变量i,只是赋的值是上一次迭代完成时的值,这样的话,循环体内获取到的i, 每次也都是全新的变量i,而不是像使用 var 声明时获得的是全局变量,而且,每一次迭代完成后,i 变量就消失了。举个简单的例子,你们一看就能明白。学习
let funs = []; // 使用var 声明循环变量i for (var i = 0; i < 10; i++) { funs.push(function(){ console.log(i); }) } // funs.forEach(item => item()); // 输出10个10 // 改成使用let 声明循环变量 let funss = []; for (let i = 0; i < 10; i++) { funss.push(function(){ console.log(i); }) } funss.forEach(item => item()); // 输出0, 1, 2, 3, 4, 5, 6, 7, 8, 9
除了常规的for 循环以外,还有for-in 和for-of 操做, 原理都是同样的,他们每一次的迭代都是从新声明一个全新的迭代对象,而不是给原来声明的迭代对象赋新值, 循环体内获取到的都是当前迭代对象的值。spa
let funcs = []; let arr = [1, 2, 3]; // for-in 循环, 数组是不建议使用for-in ,这里只是简单的演示 for (let key in arr) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 输出0, 1, 2 }); // 使用for-of funcs = []; for (let key of arr) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 输出1, 2,3 });
如今看一下const, const 也可使用在for循环中。最简单的就是把上面的三个for 循环中的let 都转换为const. for (const i = 0; i < 10; i++) {}; for (const key of arr) {} , for (const key in arr) {} . 这时你会发现第一种常规for 循环报错了。看一下第一次迭代就知道了。声明了一个 变量i, 赋值为0。 但这里使用const, 也就意味着i 在声明以后,就不能再改变了。好了,0 < 10, 执行循环体,而后 加1,报错了,i 不能变化了。一次迭代都没有走完,就报错了,说明,在使用常规for 循环时, const 不能用来声明变量。code
再来看一下,for-of, for-in, 没有问题,由于每一次的迭代都会声明一个全新的key, 全部的赋值都是给一个新的变量赋值,而没有改变原来的值。那使用let 和 const 有什么区别吗? 固然有了,仍是在于const 声明的变量不能从新赋值了,因此若是for-in 或for- of 中使用const 声明了变量( 如key), 循环体中,就不能给key 赋新值了,若是使用let ,那就无所谓了,想干什么就干什么。只不过for-in 或for-of 中,咱们不多改变key 值,因此他们在实际使用时就没有什么区别了。对象
这里再简单说一下const. 当声明一个变量时,称之为binding(绑定)。在一个做用域中声明变量的时候,至关于这个变量绑定到了该做用域中,对于const 声明的变量来讲,它的绑定更近了一步,直接绑定到一个值上。const name = "sam"; 变量name 直接绑定了一个值"sam"; 若是再更改这个绑定,就报错了。那么怎么才算更改绑定呢?就是从新赋值。name ="json" 报错了。若是name 刚开始绑定的是一个对象呢? const name = {a: 'b"}, 仍是同样,从新赋值就会报错,name={} 报错。但若是改变对象的值,则没有问题 name. a = "c"; 由于没有改变绑定。name 绑定到一个对象,就至关于咱们的地址 对应的一个真实的建筑物 . const 声明了一个变量,就至关于写了一个地址,好比,北京市东城区长安街, 绑定到一个对象上,那就是故宫了。北京市东城区长安街 绑定到了天安门对象上。那若是更改绑定,就意味着北京市东城区长安街 绑定到别的地方了,好比长城,那谁受得了,原本是想看故宫的,忽然变成游长城了。但若是改变故宫呢? 好比故宫今天安排了特别的文艺演出,没有问题啊?故宫还在那地方,按照地址仍是到故宫了。blog