首页 > JS高级程序设计:闭包例子的疑问。

JS高级程序设计:闭包例子的疑问。

function createFunction(){

    var result = new Array();
    for ( var i = 0; i < 10 ; i ++ ){
        result[i] = function(){
            return i;
        }
    }
    return result;
}


for ( let i = 0; i < createFunction().length ; i++ ){
    console.log(createFunction()[i]());
}

在看Js高级程序设计第三版的时候,看到这里;发现结果和书上描述一致,都是输出10;但是使用let之后,为什么就可以正常显示0-10;

function createFunction(){

    var result = new Array();
    for ( let i = 0; i < 10 ; i ++ ){
        result[i] = function(){
            return i;
        }
    }
    return result;
}


for ( let i = 0; i < createFunction().length ; i++ ){
    console.log(createFunction()[i]());
}

varlet的区别主要是varfunction-scope的,而letblock-scope的。这里最好的理解应该是如果用var定义的话,因为var在整个函数中持续存在,所以后面修改的值会体现到匿名函数中。而let的作用域没有那么广,所以不能影响前面已经定义的匿名函数。


用var的话,整个函数只有一个i,所有闭包里面也都是那个i,你改了i之后所有闭包也跟着一起改。

let的话会为每次循环生成一个i,闭包里面的是独立的i,而且出了循环就访问不到了。


http://es6.ruanyifeng.com/#docs/let

ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。

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的值。

【热门文章】
【热门文章】