学习ECMA6 let命令 \闭包和setTimeout\ECMA6的闭包变化

来源:互联网 发布:北京企业全网营销优化 编辑:程序博客网 时间:2024/05/18 16:14

学习ECMA6 let命令 \闭包和setTimeout\ECMA6的闭包变化


ECMA6 let命令

let实际上为JavaScript新增了块级作用域。

for循环的计数器,就很合适使用let命令。

for (let i = 0; i < arr.length; i++) {}console.log(i);//ReferenceError: i is not defined

上面代码的计数器i,只在for循环体内有效。
下面的代码如果使用var,最后输出的是10。

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

上面代码中,变量i是var声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。
如果使用let,声明的变量仅在块级作用域内有效,最后输出的是6。

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

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

闭包和setTimeout

setTimeout经常被用于延迟执行某个函数,用法为:
代码如下:

setTimeout(function(){

}, timeout);
有时为了进行异步处理,而使用setTimeout(function…,0);比如:
代码如下:

function f(){// get readysetTimeout(function(){…. // do something}, 0);return …;}

在setTimeout设定的函数处理器之前,函数f返回;
在使用异步处理时,尤其是使用闭包特性时,要特别小心;
例如:
代码如下:

for(var i = 0 ; i < 10; i++){setTimeout(function(){console.log(i);}, 0);}

对于初次使用这种方式的同学来说,很可能会认为程序会打印0…9,可结果确实打印10个10;
问题就在于,当循环完成时,function得到执行,而i已经变成10,console.log(i)中使用的是10!

加入你的目的是打印0…9,那么可以换一种方式,用函数参数来保存0….9(其实也是利用了闭包):
代码如下:

for(var i = 0 ; i < 10; i++){setTimeout((function(i){return function(){console.log(i);}})(i), 0);}

ECMA6的闭包变化

块级作用域的出现,实际上使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了。

// IIFE写法(function () {  var tmp = ...;  ...}());// 块级作用域写法{  let tmp = ...;  ...}
0 0
原创粉丝点击