JavaScript 的 setTimeout
函数详解:实现延迟执行
setTimeout
是 JavaScript 中的原生函数,用于在指定延迟(毫秒)后调用函数或执行代码片段。这在许多场景下非常有用,例如:在用户浏览页面一段时间后显示弹出窗口,或在移除元素悬停效果前添加短暂延迟(防止误操作)。
关键要点:
setTimeout
函数允许在指定毫秒数的延迟后执行函数或代码片段,这对于诸如在一定浏览时间后显示弹出窗口之类的任务非常有用。setTimeout
接受函数引用作为第一个参数,该引用可以是函数名称、引用函数的变量或匿名函数。它也可以执行代码字符串,但不建议这样做,因为这样会降低可读性、安全性并降低速度。setTimeout
执行的回调函数。但是,在延迟之后列出参数的替代方法与 IE9 及以下版本不兼容。setTimeout
执行的代码中,this
的值在与调用它的函数不同的执行上下文中运行,这在 this
关键字的上下文很重要时可能会导致问题。这可以使用 bind
、库函数或箭头函数来解决。setTimeout
的返回值是一个数字 ID,可用于结合 clearTimeout
函数取消计时器。setTimeout
使用示例
以下代码块显示了一个简单的示例,该示例将在 2 秒(2000 毫秒)的超时后将消息打印到控制台:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
为了更详细地演示这个概念,下面的演示在点击按钮两秒钟后显示一个弹出窗口:(请访问 CodePen 查看演示)
语法
根据 MDN 文档,setTimeout
的语法如下:
const timeoutID = setTimeout(code); const timeoutID = setTimeout(code, delay); const timeoutID = setTimeout(functionRef); const timeoutID = setTimeout(functionRef, delay); const timeoutID = setTimeout(functionRef, delay[, arg1, arg2, /* … ,*/ argN])
其中:
timeoutID
是一个数字 ID,可与 clearTimeout
结合使用以取消计时器。scope
指的是 Window
接口或 WorkerGlobalScope
接口。functionRef
是计时器到期后要执行的函数。code
是一种替代语法,允许您包含字符串而不是函数,该字符串在计时器到期时进行编译和执行。delay
是函数调用应延迟的毫秒数。如果省略,则默认为 0。arg1
, ..., argN
是传递给 functionRef
指定的函数的其他参数。注意:方括号 []
表示可选参数。
setTimeout
与 window.setTimeout
您会注意到,有时语法中包含 window.setTimeout
。这是为什么呢?
在浏览器中运行代码时,scope
将指代全局 window
对象。setTimeout
和 window.setTimeout
指的是同一个函数,唯一的区别是,在第二个语句中,我们将 setTimeout
方法作为 window
对象的属性来引用。
在我看来,这增加了复杂性,而好处却微乎其微。如果您定义了另一种 setTimeout
方法,该方法将在作用域链中优先找到并返回,那么您可能还有更大的问题需要担心。
在本教程中,我将省略 window
,但最终,您选择哪种语法取决于您自己。
setTimeout
方法的使用示例
setTimeout
方法接受函数引用作为第一个参数。
这可以是函数的名称:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
引用函数的变量(函数表达式):
const timeoutID = setTimeout(code); const timeoutID = setTimeout(code, delay); const timeoutID = setTimeout(functionRef); const timeoutID = setTimeout(functionRef, delay); const timeoutID = setTimeout(functionRef, delay[, arg1, arg2, /* … ,*/ argN])
或者匿名函数:
function greet() { alert('Howdy!'); } setTimeout(greet, 2000);
如上所述,也可以将代码字符串传递给 setTimeout
以供其执行:
const greet = function() { alert('Howdy!'); }; setTimeout(greet, 2000);
但是,由于以下原因,不建议这样做:
eval
,这是一种潜在的安全风险。传递参数给 setTimeout
在基本场景中,首选的跨浏览器方法是使用匿名函数作为第一个参数将参数传递给 setTimeout
执行的回调函数。
在下面的示例中,我们从 animals
数组中选择一个随机动物,并将此随机动物作为参数传递给 makeTalk
函数。然后,setTimeout
以一秒的延迟执行 makeTalk
函数:
setTimeout(() => { alert('Howdy!'); }, 2000);
注意:我使用了一个常规函数(getRandom
)从数组中返回一个随机元素。也可以使用箭头函数将其编写为函数表达式:
setTimeout('alert("Howdy!");', 2000);
我们将在下一节介绍箭头函数。这里有一个包含上述代码的 CodePen(您需要打开控制台才能查看输出)。
替代方法
从文章顶部的语法可以看出,传递参数给 setTimeout
执行的回调函数还有第二种方法。这涉及在延迟之后列出任何参数。
参考我们之前的示例,这将给我们:
function makeTalk(animal) { const noises = { cat: 'purr', dog: 'woof', cow: 'moo', pig: 'oink', } console.log(`A ${animal} goes ${noises[animal]}.`); } function getRandom(arr) { return arr[Math.floor(Math.random() * arr.length)]; } const animals = ['cat', 'dog', 'cow', 'pig']; const randomAnimal = getRandom(animals); setTimeout(() => { makeTalk(randomAnimal); }, 1000);
不幸的是,这在 IE9 或以下版本中不起作用,其中参数作为 undefined
传递。如果您不幸需要支持 IE9,则 MDN 上提供了一个 polyfill。
this
关键字的问题
setTimeout
执行的代码在其与调用它的函数不同的执行上下文中运行。当 this
关键字的上下文很重要时,这会成为问题:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
此输出的原因是,在第一个示例中,this
指向 dog
对象,而在第二个示例中,this
指向全局 window
对象(它没有 sound
属性)。
为了解决这个问题,有各种方法……
显式设置 this
的值
您可以使用 bind
来实现,bind
方法创建一个新函数,当调用该函数时,其 this
关键字将设置为提供的值(在本例中为 dog
对象)。这将给我们:
const timeoutID = setTimeout(code); const timeoutID = setTimeout(code, delay); const timeoutID = setTimeout(functionRef); const timeoutID = setTimeout(functionRef, delay); const timeoutID = setTimeout(functionRef, delay[, arg1, arg2, /* … ,*/ argN])
使用库
许多库都带有内置函数来解决此问题。例如,jQuery 的 jQuery.proxy()
方法。它接受一个函数并返回一个新函数,该函数将始终具有特定上下文。在本例中,那将是:
function greet() { alert('Howdy!'); } setTimeout(greet, 2000);
在 setTimeout
中使用箭头函数
箭头函数是在 ES6 中引入的。它们比常规函数的语法短得多:
const greet = function() { alert('Howdy!'); }; setTimeout(greet, 2000);
当然,您可以将它们与 setTimeout
一起使用,但是需要注意一点——箭头函数没有自己的 this
值。相反,它们使用封闭词法上下文的 this
值。
使用常规函数:
setTimeout(() => { alert('Howdy!'); }, 2000);
使用箭头函数:
setTimeout('alert("Howdy!");', 2000);
在第二个示例中,this
指向全局 window
对象(同样,它没有 sound
属性)。
这在将箭头函数与 setTimeout
一起使用时可能会让我们陷入困境。之前我们看到了如何为 setTimeout
中调用的函数提供正确的 this
值:
function makeTalk(animal) { const noises = { cat: 'purr', dog: 'woof', cow: 'moo', pig: 'oink', } console.log(`A ${animal} goes ${noises[animal]}.`); } function getRandom(arr) { return arr[Math.floor(Math.random() * arr.length)]; } const animals = ['cat', 'dog', 'cow', 'pig']; const randomAnimal = getRandom(animals); setTimeout(() => { makeTalk(randomAnimal); }, 1000);
当在引入的方法中使用箭头函数时,这将不起作用,因为箭头函数没有它自己的 this
值。该方法仍将记录 undefined
。
使用箭头函数和 setTimeout
编写更简洁的代码
但是,因为箭头函数没有自己的 this
值,所以它也可以为我们带来优势。
考虑这样的代码:
const getRandom = arr => arr[Math.floor(Math.random() * arr.length)];
可以使用箭头函数更简洁地重写它:
setTimeout(makeTalk, 1000, randomAnimal);
如果您想了解箭头函数的入门知识,请阅读“ES6 箭头函数:JavaScript 中简洁的语法”。
取消计时器
正如我们在文章开头了解到的那样,setTimeout
的返回值是一个数字 ID,可与 clearTimeout
函数结合使用以取消计时器:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
让我们看看它的实际效果。在下面的 Pen 中,如果您点击“开始倒计时”按钮,倒计时将开始。如果倒计时完成,小猫就赢了。但是,如果您按下“停止倒计时”按钮,计时器将被停止并重置。(如果您在倒计时达到零时没有看到很酷的效果,请使用嵌入底部右侧的按钮重新运行 Pen。)
总结
在本文中,我演示了如何使用 setTimeout
来延迟函数的执行。我还展示了如何将参数传递给 setTimeout
,如何在其回调函数内部维护 this
值,以及如何取消计时器。
setTimeout
JavaScript 函数的常见问题解答
setTimeout
在 JavaScript 中是什么?
setTimeout
是 JavaScript 中的内置函数,允许您在指定的延迟(以毫秒为单位)后安排函数或代码段的执行。
setTimeout
如何工作?
当您调用 setTimeout
函数时,您需要提供两个参数:要执行的函数或代码,以及以毫秒为单位的延迟。提供的函数/代码将添加到队列中,并在指定的延迟后,它将从队列移动到调用堆栈以执行。
使用 setTimeout
的替代方法有哪些?
是的,有替代方法,例如 setInterval
,它会以指定的间隔重复执行函数,以及较新的 requestAnimationFrame
,它用于更流畅的动画和更好的浏览器性能。
什么时候不应该使用 setTimeout
?
setTimeout
是用于在 JavaScript 中调度异步代码执行的有用工具,但在某些情况下它可能不是最佳选择。对于精确的动画或游戏,您应该使用 requestAnimationFrame
。您不应该嵌套多个 setTimeout
调用;最好使用 Promise 或异步模式。setTimeout
对小于 10 毫秒的延迟不准确;请考虑替代方案。如果您正在构建实时应用程序(如在线多人游戏或金融交易平台),请选择实时技术,如 WebSockets。大型 CPU 密集型任务可能会阻塞事件循环;如果需要,请使用 Web Workers。
我可以取消 setTimeout
操作吗?
是的,您可以使用 clearTimeout
函数取消计划的超时。它将 setTimeout
返回的超时 ID 作为参数。例如:const timeoutId = setTimeout(myFunction, 1000); clearTimeout(timeoutId);
setTimeout
和 setInterval
之间的区别是什么?
setTimeout
将函数安排在指定的延迟后运行一次,而 setInterval
将函数安排在指定的间隔重复运行,直到它被取消或程序停止。
我可以使用 setTimeout
的最小延迟值是多少?
最小延迟值为 0,这意味着该函数安排在当前线程完成但处理任何挂起的事件之前执行。但是,计时器的实际粒度因不同的浏览器和环境而异。某些环境可能不支持小于 10 毫秒的延迟。
setTimeout
在 Node.js 中是什么?
setTimeout
是 Node.js 的内置函数,用于将给定函数或代码块的执行延迟指定的毫秒数。
如何在 Node.js 中使用 setTimeout
?
您可以按如下方式使用 setTimeout
函数:setTimeout(callback, delay);
其中 callback
是您希望在指定的毫秒延迟后执行的函数。
在 Node.js 中使用 setTimeout
的最佳实践有哪些?
一些最佳实践包括使用命名函数作为回调函数,优雅地处理错误,并了解事件循环的行为以避免意外延迟或阻塞。此外,请考虑使用 setImmediate
在下一个事件循环周期中立即执行。
(请注意,由于输入文本中包含 CodePen 的链接,我无法直接在输出中呈现 CodePen 的内容。您需要访问文中提供的链接来查看 CodePen 演示。)
以上是Settimeout JavaScript函数:指南示例的详细内容。更多信息请关注PHP中文网其他相关文章!