2

我试图实现一个向用户“输入”消息的功能。像“T” - 等待 - “Th” - 等待 - “Tha” ...我想出了这个功能,但它会等待然后立即更新所有字母(而不是单独更新):

var tu = 'Thank you'
var timing = 1000
for (var i=0; i<=tu.length; i++) {
    setTimeout(function (){input.text(tu.slice(0, i))}, timing)
    timing = timing + 1000
}

但是当我这样做时(不要笑),它起作用了..

setTimeout(function (){input.text('t')}, 400)
setTimeout(function (){input.text('th')}, 800)
setTimeout(function (){input.text('tha')}, 3000)
setTimeout(function (){input.text('than')}, 4000)
setTimeout(function (){input.text('thank')}, 5000)
setTimeout(function (){input.text('thank ')}, 6000)
setTimeout(function (){input.text('thank y')}, 7000)
setTimeout(function (){input.text('thank yo')}, 8000)
setTimeout(function (){input.text('thank you')}, 9000) 

任何人都可以阐明为什么循环的行为与我的剪切粘贴工作不同吗?

4

3 回答 3

5

这是 JavaScript 中一个奇怪的作用域的例子。是获取对的setTimeout引用i而不是 的值 ifor循环在任何执行之前完成,setTimeouts因此所有setTimeouts 将使用相同的值i,即tu.length

您需要使用闭包来解决此问题:

var tu = 'Thank you'
var timing = 1000
for (var i = 1; i <= tu.length; i++) {
    (function (i) {
        setTimeout(function () {
            input.text(tu.slice(0, i))
        }, timing * i);
    })(i);
}

(另外,正如其他人所指出的,你有一个边界问题。我改为i < tu.lengthi <= tu.length

您可以在 jsFiddle 上看到这一点

于 2013-03-23T02:11:05.420 回答
2

这是因为i它的范围比你的函数更大,所以它从循环中达到 10 并在每次超时时被使用(作为 10)。

有办法解决这个问题,但最好setInterval用于这种行为;

var tu = 'Thank you'
var timing = 1000
var i=0;
var tm=setInterval(function(){
    ++i;
    input.text(tu.slice(0, i));
    if(i>=tu.length){
        clearInterval(tm);
    }
},timing)
于 2013-03-23T02:13:42.957 回答
1

你失去i了循环的范围。您必须创建一个可以i在超出范围时访问的函数。这是我的做法:

var tu = 'Thank you',
    timing = 1000;

function doPart(i) {
    setTimeout(function () {
        input.text(tu.slice(0, i));
    }, i*timing);
}

function printString() {
    var i;
    for (i=1; i<tu.length; i++) {
        doPart(i);
    }
}

printString();

另外,我认为你的意思是tu.slice(0, i+1). Slice 从开始索引到结束索引,但不包括结束索引。

于 2013-03-23T02:06:58.863 回答