使用setTimeout在浏览器循环中实现ghost writer效果

Yeo*_*eng 2 javascript

我试图实现一个向用户"输入"消息的功能.像"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
}
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做(不要笑),它的工作..

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) 
Run Code Online (Sandbox Code Playgroud)

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

Pet*_*son 5

这是JavaScript中一个奇怪的范围界面的例子.该setTimeout是获得参考i,并不值 i.该for循环之前任何的完成setTimeouts执行,因此所有的setTimeout旨意使用相同的值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);
}
Run Code Online (Sandbox Code Playgroud)

(也正如别人指出的那样,你有一个边界问题.我改i < tu.lengthi <= tu.length.)

你可以在jsFiddle上看到这个.