setTimeout
函数是一个原生的javascript函数。但是这个函数也可以在一些js库中使用,如jQuery。setTimeout
函数会在一个指定的延迟时间之后调用一个函数或执行一段指定的代码。它的应用非常广泛,例如我们希望用户在浏览器某个页面一段时间后弹出一个对话框,或者是鼠标点击某个元素后隔几秒钟在删除这个元素。
点击这里查看第一个demo
语法
在MDN documentation中,setTimeout
函数的如法如下:
var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]); var timeoutID = window.setTimeout(code, [delay]);
- timeoutID:一个数字ID号,它可以在
clearTimeout()
函数中被用来清除定时器。 - func:被执行的函数。
- code:(替代的语法)一个被执行的代码串。
- delay:延迟的时间,单位毫秒。如果没有指定,默认为0。
setTimeout vs window.setTimeout
你会注意到上面的语法书写格式是window.setTimeout
,为什么是这样呢?
setTimeout
和window.setTimeout
基本上是一样的,唯一不同的是window.setTimeout
将setTimeout
函数作为全局window
对象的一个属性来引用。
应用举例
setTimeout
函数的第一个参数接收一个函数引用。
你可以使用一个命名函数:
function explode(){ alert("Boom!"); } setTimeout(explode, 2000);
也可以使用一个变量来引用一个函数:
var explode = function(){ alert("Boom!"); }; setTimeout(explode, 2000);
你还可以使用匿名函数:
setTimeout("alert('Boom!');", 2000);
另外,我们还可以在setTimeout
函数中执行一个字符串代码块:
setTimeout("alert('Boom!');", 2000);
但是不建议使用这种方法,理由如下:
- 难以阅读,不便于管理和调试。
- 它隐含使用
eval()
方法来执行代码,这是一个潜在的安全隐患。 - 执行速度慢。
关于这方面的讨论请参考Is there ever a good reason to pass a string to setTimeout?这篇文章。
在setTimout中传入参数
通常我们首选的在setTimout
中传入参数的方法是使用匿名函数作为它的第一个参数。这种方式是可以跨浏览器使用的。
下面的例子中,我们从greetings
数组中随机选择一种问候语,并将着这个随机的问候语传入一个greet
函数,greet
函数会使用setTimeout
在1秒钟后执行这个函数。
function greet(greeting){ console.log(greeting); } function getRandom(arr){ return arr[Math.floor(Math.random()*arr.length)]; } var greetings = ["Hello", "你好", "Привет "], randomGreeting = getRandom(greetings); setTimeout(function(){ greet(randomGreeting); }, 1000);
一个替代的方法
在本文的开始提到了setTimeout
的语法,我们可以setTimeout
使用另一种方法来传递参数。
setTimeout(greet, 1000, randomGreeting);
不幸的是这种方法在IE9及以下的IE浏览器会报错-参数undefined
。
“this”引用的问题
setTimeout
中执行的函数会在一个单独的上下文环境中被执行,如果函数中有this
引用,有可能会得到意想不到的结果。
var person = { name: "张三", introduce: function(){ console.log("你好, 我是 " + this.name); } }; person.introduce(); // Outputs: 你好,我是张三 setTimeout(person.introduce, 50); // Outputs: 你好,我是 undefined
在上面的代码中,第一个输出代码中的this
指的是person
对象,而第二个输出代码中的this
指的是全局的window
对象(这个对象没有name
属性)。
明确设置“this”引用的值
你可以通过bind()方法啦创建一个新的函数,在调用的时候,将this
关键字明确的指定为它的参数指定的对象。代码如下:
setTimeout(person.introduce.bind(person), 50);
注意:bind
方法是在ECMAScript 5引入的,所以它只能在大部分现代浏览器中正常运行。
使用jQuery来解决这个问题
大多数的js库都有内置的函数来解决这个问题。例如jQuery的jQuery.proxy()方法。
取消定时器
setTimeout
函数的返回值是一个数值型的ID标识符。我们可以使用这个ID在clearTimeout()
函数中用来取消setTimeout
函数设定的定时器。
var timer = setTimeout(myFunction, 3000); clearTimeout(timer);
下面是一个非常有意思的例子。有两个按钮,一个是用于开始计时,一个用于取消计时。如果你点击开始计时后,3秒钟时间没有点击取消定时按钮,小猫就会从原来的位置上掉了下去。
你可以查看第三个demo来看看效果!
注意事项
要注意一个潜在的问题是setTimeout
函数是异步的。它会在当前调用栈执行完毕之后才被执行。它不会并发执行或在一个单独的线程中执行(javascript是一种单线程的语言)。
console.log(1); setTimeout(function(){ console.log(2); }, 0); console.log(3); // 输出: 1, 3, 2
这也是在使用原生的javascript setTimeout
函数和使用jQuery delay方法时照成一些混乱的原因。
delay
方法是在一个给定的jQuery序列之间添加一些延迟时间。我们是没有办法取消这个延迟的。例如,你想要将一幅图片在1秒时间内淡入淡出显示,然后延迟5秒钟,再在1秒钟时间内淡入淡出大的将它隐藏,可以使用下面的代码:
$("img").fadeIn(1000).delay(5000).fadeOut(1000);
最后,如果你想要在指定时间之后重复执行某些代码,可以使用setInterva
函数。
小结
在这篇文章中,我们介绍了setTimeout
函数,以及如何向setTimeout
函数中传入参数和关于setTimeout
函数中使用this
关键字的注意事项。理解和掌握setTimeout
函数是制作一些动画效果的基础,希望你能认真学习体会!