当我玩诺言时,我发现这段代码非常奇怪,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();
答案 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
的方式提升是:
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;
此处,let i = i
显示Uncaught ReferenceError: i is not defined
,其中显示了名称冲突导致外部范围中的i
无法访问的根本原因。将此与var i
,进行对比,由于提升而编译没有错误,以及with a similar script in bash
(它以不同于Javascript的方式处理范围,因此按您描述的方式工作)。