setTimeout
是一个本机JavaScript函数(尽管它可以与jQuery之类的库一起使用,我们将在后面看到),它会在指定的延迟(以毫秒为单位)后调用一个函数或执行一个代码段。 例如,如果您希望在访问者浏览页面一定时间后显示弹出窗口,或者希望在从元素上移除悬停效果之前等待一小段时间(以防用户意外地将其弹出),这可能会很有用。鼠标移出)。
为了演示该概念,下面的演示在单击按钮两秒钟后显示一个弹出窗口。
请参阅CodePen上的SitePoint ( @SitePoint )的Pen Delayed Magnific Popup模式 。
如果您没有看到弹出窗口,请访问CodePen并在那里运行演示。
从MDN文档中 , setTimeout
的语法如下:
var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);
哪里:
timeoutID
是数字ID,可与clearTimeout()
结合使用以取消计时器。 scope
是指Window接口或WorkerGlobalScope接口 。 function
是计时器到期后要执行的功能。 code
(使用替代语法)是要执行的代码字符串。 delay
是函数调用应延迟的毫秒数。 如果省略,则默认为0。 注意:方括号[]
表示可选参数。
您会注意到上面的语法使用scope.setTimeout
。 为什么是这样?
好吧,在浏览器中运行代码时, scope
将引用全局window
对象。 setTimeout
和window.setTimeout
引用相同的函数,唯一的区别是在第二条语句中,我们将setTimeout
方法引用为window
对象的属性。
我认为,这增加了复杂性,几乎没有好处。 如果您定义了一个替代的setTimeout
方法,该方法将在范围链中优先找到并返回,那么您可能会担心更大的问题。
在本教程中,我将省略window
,但是最终,您可以选择哪种语法由您决定。
setTimeout
接受对函数的引用作为第一个参数。
这可以是函数的名称:
function explode(){
alert("Boom!");
}
setTimeout(explode, 2000);
引用函数的变量:
var explode = function(){
alert("Boom!");
};
setTimeout(explode, 2000);
或匿名函数:
setTimeout(function(){
alert("Boom!");
}, 2000);
还可以传递setTimeout
字符串以使其执行:
setTimeout("alert('Boom!');", 2000);
但是,出于以下原因,不建议这样做:
eval()
,这是潜在的安全风险 这个StackOverflow问题提供了以上几点的更多信息。
在基本方案中,将参数传递给setTimeout
执行的回调的首选跨浏览器方法是使用匿名函数作为第一个参数。
在以下示例中,我们从greetings
数组中选择一个随机问候greetings
,并将此随机问候语作为参数传递给greet
函数,该函数由setTimeout
执行,延迟一秒:
function greet(greeting){
console.log(greeting);
}
function getRandom(arr){
return arr[Math.floor(Math.random()*arr.length)];
}
var greetings = ["Hello", "Bonjour", "Guten Tag"],
randomGreeting = getRandom(greetings);
setTimeout(function(){
greet(randomGreeting);
}, 1000);
JS斌
从文章顶部的语法可以看出,还有第二种方法将参数传递给setTimeout
执行的回调。 这涉及在延迟后列出所有参数。
参考前面的示例,这将为我们提供:
setTimeout(greet, 1000, randomGreeting);
不幸的是,这在IE9或更低版本(参数通过undefined
传递)中不起作用。 但是, MDN上有可用的pollyfill 。
this
setTimeout
执行的代码在与调用它的函数不同的执行上下文中运行。 当this
关键字的上下文很重要时,这是有问题的:
var person = {
firstName: "Jim",
introduce: function(){
console.log("Hi, I'm " + this.firstName);
}
};
person.introduce();
// Outputs: Hi, I'm Jim
setTimeout(person.introduce, 50);
// Outputs: Hi, I'm undefined
该输出的原因是,在第一个示例中, this
指向person
对象,而在第二个示例中, this
指向全局window
对象(不具有firstName
属性)。
为了解决这个问题,有多种措施:
this
您可以使用bind方法来执行此操作,该方法将创建一个新函数,该函数在被调用时将其this
关键字设置为提供的值(在本例中为person
对象)。 这将给我们:
setTimeout(person.introduce.bind(person), 50);
注意: bind
是ECMAScript 5中引入的,因此仅适用于更现代的浏览器 。 您可以在此SitePoint文章中了解有关它的更多信息(以及其他设置this
值的方法)。
许多库都带有内置函数来解决此问题。 例如,jQuery的jQuery.proxy()方法。 这需要一个函数并返回一个始终具有特定上下文的新函数。 在我们的情况下,将是:
setTimeout($.proxy(person.introduce, person), 50);
JS斌
ES6引入了箭头功能。 它们的语法比常规函数短得多:
(param1, param2, paramN) => expression
您当然可以将它们与setTimeout
一起使用,但要注意一个陷阱-即,箭头函数没有自己的this
值。 而是使用封闭的词汇上下文的this
值。
使用常规函数:
const person = {
firstName: "Jim",
introduce: function() {
console.log(`Hi, I'm ${this.firstName}`);
}
};
person.introduce();
// Hi, I'm Jim
使用箭头功能:
const person = {
firstName: "Jim",
introduce: () => {
console.log(`Hi, I'm ${this.firstName}`);
}
};
person.introduce();
// Hi, I'm undefined
在第二个示例中, this
指向全局window
对象(不具有firstName
属性)。
在setTimeout
使用箭头功能时,这可能会使我们绊倒。 以前,我们看到了如何为setTimeout
提供一个具有正确的this
值的函数:
setTimeout(person.introduce.bind(person), 50);
当在introduce
方法中使用箭头功能时,此功能将无效,因为箭头功能没有自己的this
值。 该方法仍将记录undefined
。
但是,由于箭头函数没有自己的this
值,因此它也可以发挥我们的优势。
这样的代码...
var person = {
firstName: "Jim",
delayedIntroduce: function() {
setTimeout(
function() {
console.log("Hi, I'm " + this.firstName);
}
.bind(this)
, 1000);
}
}
person.delayedIntroduce();
…可以使用箭头功能更简洁地重写:
const person = {
firstName: "Jim",
delayedIntroduce() {
setTimeout(
() => { console.log(`Hi, I'm ${this.firstName}`); }, 1000
);
}
}
person.delayedIntroduce();
如果您想了解箭头功能的入门知识,请阅读ES6箭头功能:JavaScript中的简洁语法 。
setTimeout
的返回值是一个数字ID,可与clearTimeout
函数结合使用以取消计时器:
var timer = setTimeout(myFunction, 3000);
clearTimeout(timer);
让我们看看实际情况。 在下面的笔中,如果单击“ 开始倒数”按钮,则将开始倒数。 如果倒计时完成,小猫就会得到它。 但是,如果按停止倒数按钮,计时器将被暂停并重置。 (如果倒数到零时看不到很酷的效果,请使用嵌入右下角的按钮重新运行笔。)
请参阅CodePen上SitePoint ( @SitePoint )的Pen SetTimeout小猫 。
需要注意的一个潜在警告是setTimeout
是异步的,因为它会将接收到的函数引用排队,以在当前调用堆栈完成执行后运行。 但是,它不能同时执行,也不能在单独的线程上执行(由于JavaScript具有单线程性质)。
console.log(1);
setTimeout(function(){
console.log(2);
}, 0);
console.log(3);
// Outputs: 1, 3, 2
在使用本机JavaScript setTimeout
函数和jQuery的delay方法之间也存在一些混淆。
delay
方法专门用于在给定jQuery队列中的方法之间添加延迟。 无法取消延迟。 例如,如果要使图像淡入淡出一秒钟,使其可见五秒钟,然后淡出一秒钟,则可以执行以下操作:
$("img").fadeIn(1000).delay(5000).fadeOut(1000);
setTimeout
最好用于其他所有功能。
最后,如果需要在指定的延迟后重复执行代码,则setInterval
更适合该工作。 您可以在此处阅读有关此功能的更多信息 。
在本文中,我演示了如何使用setTimeout
延迟函数的执行。 我还展示了如何将参数传递给setTimeout
,如何在回调函数中维护this
值以及如何取消计时器。
如果您想了解更多信息,SitePoint Premium中有一个完整的JavaScript书库 。
如果您想讨论本文的内容,请在评论中进行。 但是,如果您遇到了与setTimeout
(或其他任何事情)有关的编码问题,那么请前往SitePoint论坛 。 您可以使用(Google,Facebook,Twitter,Yahoo,GitHub或通过创建帐户)登录。 然后前往JavaScript论坛并启动一个线程来说明您的问题。
From: https://www.sitepoint.com/jquery-settimeout-function-examples/