Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript变量复制范围_Javascript_Function_Scope_Closures - Fatal编程技术网

Javascript变量复制范围

Javascript变量复制范围,javascript,function,scope,closures,Javascript,Function,Scope,Closures,我有两段代码,我相信它们会产生相同的结果: 一, 用于(var i=0;i这是setTimeout,它延迟执行直到浏览器可用,或者在本例中是0.1秒之后,当循环阻塞浏览器时,直到循环完成后才会执行超时,此时变量i等于它在循环中设置的最后一个值,因为循环在此之前已经完成或者执行setTimeout中的代码 通过将变量作为循环内的参数传递给另一个函数,该变量是该函数作用域的局部变量,并使其值与迭代无关 for(var i=0;i<10;i+=1){ var j=i;

我有两段代码,我相信它们会产生相同的结果:

一,


用于(var i=0;i这是setTimeout,它延迟执行直到浏览器可用,或者在本例中是0.1秒之后,当循环阻塞浏览器时,直到循环完成后才会执行超时,此时变量
i
等于它在循环中设置的最后一个值,因为循环在此之前已经完成或者执行setTimeout中的代码

通过将变量作为循环内的参数传递给另一个函数,该变量是该函数作用域的局部变量,并使其值与迭代无关

for(var i=0;i<10;i+=1){
    var j=i;                // j is constantly updated and it's also hoisted
    setTimeout(function(){  // and this runs last, when the browser is no longer
        console.log(j);     // locked, so j is the last value it was set to
    },100);
}

在第一个代码示例中,
for(var i=0;i在循环的迭代中,
j
没有绑定
i
的值。这是因为不能在循环中声明变量。循环在JavaScript中没有作用域,只有函数有作用域

第一个代码示例相当于:

var i, j; // all variable declarations are hoisted to the top
for (i = 0; i < 10; i += 1) {
    j = i;
    setTimeout(function() {
        console.log(j);
    }, 100);
}
var i,j;//所有变量声明都被提升到顶部
对于(i=0;i<10;i+=1){
j=i;
setTimeout(函数(){
控制台日志(j);
}, 100);
}
由于在第二个代码示例中,
j
是在匿名立即数函数中声明的,因此它在该迭代中绑定到
i
的值,这是一个传递值技巧。这称为关闭范围或简单的闭包

var j在每次迭代中创建一个新变量j

for(var i=0;i<10;i+=1){
    var j=i;                // j is constantly updated and it's also hoisted
    setTimeout(function(){  // and this runs last, when the browser is no longer
        console.log(j);     // locked, so j is the last value it was set to
    },100);
}
不幸的是,您所想的并不是Javascript所想的。在Javascript中,所有变量声明都会移动到封闭函数的顶部,因此当您键入

function(){
    for(var i=1; i<10; i++){
然而,在Javascript中,内部变量声明被挂起,因此实际上就像您编写了

var x;
x = 1;
if(true){
   x = 2;
}
console.log(x);
第二种方法是使用闭包来保持i的值

事实上,您看到的两个结果都是闭包工作方式的结果。您传递给
setTimeout
的两个函数都是闭包

我认为第一个也应该保留价值,因为:

var j在每次迭代中创建一个新变量j

for(var i=0;i<10;i+=1){
    var j=i;                // j is constantly updated and it's also hoisted
    setTimeout(function(){  // and this runs last, when the browser is no longer
        console.log(j);     // locked, so j is the last value it was set to
    },100);
}
不,它没有。在第一个示例中只有一个
j
。在JavaScript中(目前),变量具有函数或全局作用域,从不阻塞作用域。JavaScript对第一个示例的实际作用看起来更像这样:

var i;
var j;

for(i=0;i<10;i+=1){
    j=i;
    setTimeout(function(){
        console.log(j);
    },100);
}
相反:

for(var i=0;i<10;i+=1){
    setTimeout(makeHandler(i));
}

function makeHandler(j){
    return function(){
        console.log(j);
    };
}

for(var i=0;i这是可行的,使用
let
而不是
var
let
在2013年被问到这个问题时并不存在):


用于(设i=0;iso
var j
不会在每次迭代中创建新的j?不,for循环中没有特殊的作用域,因此j是循环所处的任何作用域的局部,变量被提升,所以你需要一个闭包来保持引用期间的值不变,这是一个很好的术语。你想到了吗?@FritsvanCampen:是的,我花了一段时间但是当我最终这样做的时候,我很高兴。”在每次迭代中,
var j
创建一个新的变量j“不,它没有。
var x;
x = 1;
if(true){
   x = 2;
}
console.log(x);
var i;
var j;

for(i=0;i<10;i+=1){
    j=i;
    setTimeout(function(){
        console.log(j);
    },100);
}
for(var i=0;i<10;i+=1){
    var f1 = function(j){
        var f2 = function(){
            console.log(j);
        };
        setTimeout(f2,100);
    };
    f1(i);
}
for(var i=0;i<10;i+=1){
    setTimeout(makeHandler(i));
}

function makeHandler(j){
    return function(){
        console.log(j);
    };
}
for(let i=0;i<10;i+=1){
    let j=i;
    setTimeout(function(){
        console.log(j);
    },100);
}