Javascript 为什么setTimeout回调中的变量没有预期值? $(文档).ready(函数(){ 幻灯片(3,“图像控制”,5000600); }); 功能幻灯片(numberOfImages、containerId、延时、像素){ //从第一个图像开始 var i=0; var style=document.getElementById(containerId).style; setInterval(函数(){ 如果(i>=numberOfImages){ i=0; } var marginLeft=(-600*i); var pixelmotation=像素/15; ////////////////////////////////////////看这里////////////////////////////// 对于(var j=0;j*像素移动

Javascript 为什么setTimeout回调中的变量没有预期值? $(文档).ready(函数(){ 幻灯片(3,“图像控制”,5000600); }); 功能幻灯片(numberOfImages、containerId、延时、像素){ //从第一个图像开始 var i=0; var style=document.getElementById(containerId).style; setInterval(函数(){ 如果(i>=numberOfImages){ i=0; } var marginLeft=(-600*i); var pixelmotation=像素/15; ////////////////////////////////////////看这里////////////////////////////// 对于(var j=0;j*像素移动,javascript,Javascript,不能在setTimeout函数中直接使用变量j,因为该函数在for循环完成后运行一段时间,因此j具有终止值,而不是调用setTimeout时的值 您可以在setTimeout函数中可用的函数闭包中捕获j的当前值,如下所示: <div id="image_cont"> <img src="images/pic1.jpg" alt="pic1" /> <img src="images/pic2.jpg" alt="pic2" /> <img sr

不能在setTimeout函数中直接使用变量j,因为该函数在
for
循环完成后运行一段时间,因此j具有终止值,而不是调用setTimeout时的值

您可以在setTimeout函数中可用的函数闭包中捕获j的当前值,如下所示:

<div id="image_cont">
  <img src="images/pic1.jpg" alt="pic1" />
  <img src="images/pic2.jpg" alt="pic2" />
  <img src="images/pic3.jpg" alt="pic3" />
</div>

$(document).ready(function() {
    slide(3, "image_cont", 5000, 600);
});

function slide(numberOfImages, containerId, timeDelay, pixels) {
    //start on first image
    var i = 0;
    var style = document.getElementById(containerId).style;
    window.setInterval(function() {
        if (i >= numberOfImages){
            i = 0;
        }
        var marginLeft = (-600 * i);
        var pixelMovement = pixels/15;


////////////////////////////////////////LOOK HERE//////////////////////////////


        for (var j = 0; j * pixelMovement < 600; j++){
            window.setTimeout(function(){
//alert('marginLeft: ' + marginLeft + ' j: ' + j + ' pixelMovement: ' + pixelMovement);
//this alert shows j is 15 when it should be 0, what's going on?


/////////////////////////////////////////END//////////////////////////////////
                style.marginLeft = (marginLeft - j * pixelMovement) + "px";
                }, 150);
        }
        i++;
    }, timeDelay);
}
for(var j=0;j*像素移动<600;j++){
设置超时(函数(cntr){
返回函数(){
style.marginLeft=(marginLeft-cntr*像素移动)+“px”;
};
}(j)150人;
}

我觉得这种类型的闭包有点让人困惑。我会尽力解释发生了什么事。我们将执行一个匿名函数的结果传递给
setTImeout()
函数,该匿名函数接受一个参数(我在这里将其命名为cntr),并将
j
的值作为该参数的值传递。当该函数执行时(现在其内部有可用的
j
),该函数返回另一个匿名函数。另一个匿名函数是
setTimeout
在启动时实际调用的函数。但是,第二个匿名函数位于第一个函数的函数闭包内,第一个函数的捕获值为
j
(作为一个变量,我在函数闭包内重命名了
cntr
,以避免解释时出现混淆)。正是匿名函数让它如此混乱,但它可以工作。

它应该是任何东西,因为
window.setTimeout
是一个“异步”函数,所以它在执行后立即返回


因此,在您的代码中,for循环的
保持循环,一段时间(150ms)后,您的函数正在执行,并且
j
变量的实际值被打印出来。

您创建并传递给
setTimeout
的函数都引用了相同的循环计数器变量
j
——在循环运行之后,
j
将设置为导致循环终止的值。您需要使用闭包来确保在内部循环中创建的函数能够访问定义函数时的值
j
had

有关问题和解决方案的更多详细信息,请参阅此答案:

(愚蠢的变量名称,以明确它与
j
不同):


可以添加页面的HTML吗?它似乎对我来说很好,但是你不能用
$('containerId')
替换
document.getElementById(containerId)
?只有一个变量名为
j
谢谢你的课,我想我基本上理解了它。不幸的是,我的脚本仍以意外的方式运行。我的魔法还不够强大。
for (var j = 0; j * pixelMovement < 600; j++){
    window.setTimeout(function(cntr) {
        return function() {
            style.marginLeft = (marginLeft - cntr * pixelMovement) + "px";
        };
    } (j), 150);
}
window.setTimeout((function(jWhenFunctionWasDefined) {
  return function() {
    style.marginLeft = (marginLeft - jWhenFunctionWasDefined * pixelMovement) + "px";
  }
})(j), 150)