为什么promise中的var i函数是未定义的?

时间:2016-09-08 17:25:42

标签: promise closures

当我玩诺言时,我发现这段代码非常奇怪,var"我"在那时函数是未定义的。

function api(){
    return new Promise(function(resolve, reject) {
            setTimeout(function(){
                resolve(['x','y','z']);
            },2000)
        });
}


for(var i=0;i<3;i++){
    (function (){//closure
        var i=i;
        api().then(function(re){
            console.log(re[i]);
        })
    })()
}

// this broken too
for(var i=0;i<3;i++){
    (function(){
        var i=i;
        console.log(i);
    })()
}

我认为这是因为将var定义为同名,但在其他情况下,这种类型的定义都可以。我以这种方式改变了var。 以下都可以正常工作

function api(){
    return new Promise(function(resolve, reject) {
            setTimeout(function(){
                resolve(['x','y','z']);
            },2000)
        });
}


for(var i=0;i<3;i++){
    (function (){//closure
        var j=i;
        api().then(function(re){
            console.log(re[j]);
        })
    })()
}

for(var i=0;i<3;i++){
    var i=i;
    console.log(i);
}

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

var a=1;
var a=a.toString();

1 个答案:

答案 0 :(得分:1)

因为你在闭包中定义了i,所以它会从作用域之外篡改i(然后将无法访问)。在Javascript中,vars的作用域是函数,而不是块,因此在for循环中声明var i = i纯粹是多余的。

  

var hoisting

     

因为变量声明(和一般的声明)是   在执行任何代码之前处理,在任何地方声明变量   在代码中相当于在顶部声明它。这也意味着   变量在声明之前似乎可以使用。这个   行为被称为&#34;吊装&#34;,因为看起来变量   声明被移动到函数或全局代码的顶部。

有关MDN's var article的更多信息,请参阅

有关吊装隐藏根本原因的原因的详细信息,请比较将var i = i更改为let i = i时发生的情况,因为let未按var的方式提升是:

&#13;
&#13;
function api(){
    return new Promise(function(resolve, reject) {
            setTimeout(function(){
                resolve(['x','y','z']);
            },2000)
        });
}


for(var i=0;i<3;i++){
    (function (){//closure
        let i=i;
        api().then(function(re){
            console.log(re[i]);
        })
    })()
}
&#13;
&#13;
&#13;

此处,let i = i显示Uncaught ReferenceError: i is not defined,其中显示了名称冲突导致外部范围中的i无法访问的根本原因。将此与var i进行对比,由于提升而编译没有错误,以及with a similar script in bash(它以不同于Javascript的方式处理范围,因此按您描述的方式工作)。