Javascript 打字机片段使浏览器无响应
Javascript typewriter snippet makes browser not responding
我有一种方法可以使用 Javascript
为我的文本添加打字机效果。我使用以下代码片段来做到这一点:
const text = document.querySelector('.type')
const content = text.textContent
let counter = 0
text.textContent = ''
while (counter < content.length) {
setTimeout(function () {
text.textContent += content[counter];
counter += 1
}, 1000)
}
我知道这种方法看起来很荒谬,但我很好奇为什么要这样做。
当我尝试 运行 此代码段时,浏览器 (Chrome) 变得没有响应。
我想知道这段代码是否会产生无限循环,为什么?如果有人可以为我提供一些替代方法来获得想要的结果。
因为setTimeout里面的counter
和外面的counter
不一样。如果您在一段时间后执行控制台登录计数器,它仍然是 0。
这与作用域有关,这里解释得太多了,但这正是您要找的。简单的解释是,在 function(){}
内部,现在在 setTimeout()
中应用,该函数外部的变量不存在。
因为它不是同一个变量,外面的变量永远不会更新,所以你的循环永远不会停止添加更多超时,所以你的浏览器永远不会停止。
除此之外,在您当前的代码中,所有字符将在 1000 毫秒后同时出现。 setTimeout 不会使 while "wait" 1000ms,它只是告诉 javascript "do this taks, after 1000" 然后继续。你创建一个类似队列的东西,告诉他们在 1000 毫秒后完成该任务。
这两个问题的解决方案(但请仔细阅读范围!),就是利用这些知识为您带来优势:
while (counter < content.length) {
setTimeout(function () {
text.textContent += content[counter];
}, 1000 * counter++)
}
现在我们再次将它们全部放入 'queue',但这次我们告诉每个下一个再等待 1000 毫秒。
setTimeout
不是 'sleep for 1sec then do the code then continue'。
setTimeout
的作用是将其代码添加到 'heap' 并继续 运行 下一行。在超时时间(1000 毫秒)后,执行堆中的代码。
因此,您的函数不断向堆中添加代码,持续 1000 毫秒,直到触发第一次超时(它不会触发,因为您不断添加新的超时 - 进程卡住了),当它应该递增时柜台.
感谢 @Martijn & @Alex Brohshtut 帮助我识别问题并提供有用的解决方案。
我确实使用他们的通知维护我的代码并通过互联网查找,最后我以这种方式做到了:
const text = document.querySelector('.type')
const content = text.textContent
let counter = 0
text.textContent = ''
while (counter < content.length) {
setTimeout((function (counterCopy) {
return function () {
text.textContent += content[counterCopy];
}
}(counter)), 1000 * counter++)
}
这是我的第一个代码的问题:
我在setTimeout
的回调函数里面只修改了变量counter
的值,它的值没有由于范围原因在循环内发生变化。所以这是一个无限循环,让我的浏览器一晚上都没有响应。
解决方案:我不得不在回调函数外更改counter
的值
我误解了setTimeout
函数,以为它会让脚本停止一段时间然后继续。两位朋友向我展示了它只安排在特定时间后执行其内部的回调函数。所以,我不得不在每次迭代中增加那个时间。
解决方案:我采纳了@Martijn的建议,用了1000 * counter++
的时间。
当我让 setTimeout
中的函数在 1000 毫秒后执行时,循环继续并增加 counter
的值。所以当函数被执行时,计数器现在的最高值等于 content.length
.
解决方案:我使用了一个函数调用,returns 回调函数本身,但这次使用计数器作为它的参数。这让我有点困惑,但最后效果很好。
setTimeout((function(counterCopy){
return function() {
console.log(counterCopy)
}
}(counter)), 1000 * counter++)
我在 YouTube 教程中看到的另一种方法 HERE
使用 setInterval
代替 setTimeout
:
const text = document.querySelector('.type')
const content = text.textContent
let counter = 0
text.textContent = ''
var typewriter = setInterval(function(){
text.textContent += content[counter];
counter++;
if (counter > (content.length - 1)) {
clearInterval(typewriter);
}
}, 1000);
我有一种方法可以使用 Javascript
为我的文本添加打字机效果。我使用以下代码片段来做到这一点:
const text = document.querySelector('.type')
const content = text.textContent
let counter = 0
text.textContent = ''
while (counter < content.length) {
setTimeout(function () {
text.textContent += content[counter];
counter += 1
}, 1000)
}
我知道这种方法看起来很荒谬,但我很好奇为什么要这样做。 当我尝试 运行 此代码段时,浏览器 (Chrome) 变得没有响应。 我想知道这段代码是否会产生无限循环,为什么?如果有人可以为我提供一些替代方法来获得想要的结果。
因为setTimeout里面的counter
和外面的counter
不一样。如果您在一段时间后执行控制台登录计数器,它仍然是 0。
这与作用域有关,这里解释得太多了,但这正是您要找的。简单的解释是,在 function(){}
内部,现在在 setTimeout()
中应用,该函数外部的变量不存在。
因为它不是同一个变量,外面的变量永远不会更新,所以你的循环永远不会停止添加更多超时,所以你的浏览器永远不会停止。
除此之外,在您当前的代码中,所有字符将在 1000 毫秒后同时出现。 setTimeout 不会使 while "wait" 1000ms,它只是告诉 javascript "do this taks, after 1000" 然后继续。你创建一个类似队列的东西,告诉他们在 1000 毫秒后完成该任务。
这两个问题的解决方案(但请仔细阅读范围!),就是利用这些知识为您带来优势:
while (counter < content.length) {
setTimeout(function () {
text.textContent += content[counter];
}, 1000 * counter++)
}
现在我们再次将它们全部放入 'queue',但这次我们告诉每个下一个再等待 1000 毫秒。
setTimeout
不是 'sleep for 1sec then do the code then continue'。
setTimeout
的作用是将其代码添加到 'heap' 并继续 运行 下一行。在超时时间(1000 毫秒)后,执行堆中的代码。
因此,您的函数不断向堆中添加代码,持续 1000 毫秒,直到触发第一次超时(它不会触发,因为您不断添加新的超时 - 进程卡住了),当它应该递增时柜台.
感谢 @Martijn & @Alex Brohshtut 帮助我识别问题并提供有用的解决方案。
我确实使用他们的通知维护我的代码并通过互联网查找,最后我以这种方式做到了:
const text = document.querySelector('.type')
const content = text.textContent
let counter = 0
text.textContent = ''
while (counter < content.length) {
setTimeout((function (counterCopy) {
return function () {
text.textContent += content[counterCopy];
}
}(counter)), 1000 * counter++)
}
这是我的第一个代码的问题:
我在
setTimeout
的回调函数里面只修改了变量counter
的值,它的值没有由于范围原因在循环内发生变化。所以这是一个无限循环,让我的浏览器一晚上都没有响应。解决方案:我不得不在回调函数外更改
counter
的值我误解了
setTimeout
函数,以为它会让脚本停止一段时间然后继续。两位朋友向我展示了它只安排在特定时间后执行其内部的回调函数。所以,我不得不在每次迭代中增加那个时间。解决方案:我采纳了@Martijn的建议,用了
1000 * counter++
的时间。当我让
setTimeout
中的函数在 1000 毫秒后执行时,循环继续并增加counter
的值。所以当函数被执行时,计数器现在的最高值等于content.length
.解决方案:我使用了一个函数调用,returns 回调函数本身,但这次使用计数器作为它的参数。这让我有点困惑,但最后效果很好。
setTimeout((function(counterCopy){ return function() { console.log(counterCopy) } }(counter)), 1000 * counter++)
我在 YouTube 教程中看到的另一种方法 HERE
使用 setInterval
代替 setTimeout
:
const text = document.querySelector('.type')
const content = text.textContent
let counter = 0
text.textContent = ''
var typewriter = setInterval(function(){
text.textContent += content[counter];
counter++;
if (counter > (content.length - 1)) {
clearInterval(typewriter);
}
}, 1000);