时间延迟函数详解

js是单线程言语,但它许可经由过程设置超时价和间歇时刻值来调理代码在特定的时刻实行。setTimeout是在指定delay时刻后,将指定要领作为异步使命增加到异步使命行列中,而setInterval则是能够轮回地每隔一个delay就向异步使命行列中增加一个使命

语法

setTimeout

// 返回唯一的ID
let timeoutID = window.setTimeout(func[, delay, param1, param2, ...]);
let timeoutID = window.setTimeout(code[, delay]);

setInterval

// 返回唯一的ID
let intervalID = window.setInterval(func, delay[, param1, param2, ...]);
let intervalID = window.setInterval(code, delay);

clearTimeout和clearInterval

window.clearTimeout(timeoutID)
window.clearInterval(intervalID)
  • timeoutID/intervalID 能够用来作为clearTimeout/clearInterval要领的参数

  • func是在delay毫秒以后实行的函数

  • code 在第二种语法,是指你想要在delay毫秒以后实行的代码字符串 (运用该语法是不引荐的, 不引荐的缘由和eval()一样)

  • delay 是耽误的毫秒数 (一秒即是1000毫秒),函数的挪用会在该耽误以后发作。假如省略该参数,delay取默认值0。现实的耽误时刻能够会比 delay 值长,缘由看下面的引见。另外,依据w3c文档得知,当delay小于0的时刻,delay按0来盘算

setTimeout 和setInterval的运用要领相似,重点以setTimeout为例,有差别的处所再零丁剖析。

例子

1、比较一下下面两个函数的区分

setTimeout(function () {
  func1()
}, 0)

setTimeout(function () {
  func1()
})

0秒耽误,此回调将会放到一个能马上实行的时段举行触发。javascript代码大体上是自顶向下的,但中心穿插着有关DOM衬着,事宜回应等异步代码,他们将构成一个行列,零秒耽误将会完成插队操纵。不写第二个参数,浏览器自动设置时刻,在IE,FireFox中,第一次配能够给个很大的数字,100ms高低,往后会缩小到最小时刻距离,Safari,chrome,opera则多为10ms高低。
—出自《javascript框架设想》

假如对0s的例子不明白,没关系,我们继承看下面这个:

var arr = [1,2,3];
for(var i in arr){
  setTimeout(function(){console.log(arr[i])},0);
  console.log(arr[i]);
}

控制台会打印什么?

 1
 2
 3
 3  //3次

虽然setTimeout函数在每次轮回的最先就挪用了,然则却被放到轮回完毕才实行,轮回完毕,i=3,接着一连打印了3次3。
这里触及到了js单线程实行的题目:js在浏览器中是单线程实行的,必须在完成当前使命后才实行行列中的下一个使命。另外关于js还维护着一个setTimeout行列,未实行的setTimeout使命就按先后递次排在行列中,比及主线程的一般使命行列实行完后,主线程就按递次实行积聚在setTimeout中的使命。所以上面的题目会先打印1、2、3.末了才打印3个3。

此时就有个疑问了,设置delay为0,而现实是大于0才实行的,何须呢?
现实上这里我们重要用来转变使命的实行递次,由于浏览器会在实行完当前使命行列中的使命,再实行setTimeout行列中积聚的使命。经由过程设置使命在耽误到0s后实行,就可以转变使命实行的先后递次,耽误该使命发作,使之异步实行。

2、delay后能够通报第三个及多个参数。

for (var i = 1; i < 4; i++) {
  var t = setTimeout(function(i) {
    console.log(i); // 2\. 1  4.2
    console.log(t); // 3\. 3  5.3
    clearTimeout(t);
  }, 10, i);
}
console.log(i);

控制台会打印什么?

 4
 1
 3
 2
 3

此处在每次轮回中,都将i作为回调函数的参数i传入,第一次传入1,第二次传入2,第三次传入3。第四次不满足轮回前提,跳出轮回,然后实行console.log(i)。主线程实行完当前使命队里的使命,然后最先实行seTimeout的行列。此时t为setTimeout末了的返回ID值3,则一次打印1,3 2,3。由于clearTimeout清晰了id为3的延时使命,所以只实行了两次。故一次打印41323
仅IE不支持第三个及以上参数

3、关于this指向的题目

myArray = ["zero", "one", "two"];
myArray.myMethod = function (sProperty) {
    alert(arguments.length > 0 ? this[sProperty] : this);
};

myArray.myMethod(); // prints "zero,one,two"
myArray.myMethod(1); // prints "one"
setTimeout(myArray.myMethod, 1000); // prints "[object Window]" after 1 second
setTimeout(myArray.myMethod, 1500, "1"); // prints "undefined" after 1,5 seconds

由setTimeout()挪用的代码运行在与地点函数完整星散的实行环境上. 这会致使,这些代码中包括的 this 关键字会指向 window (或全局)对象,这和所希冀的this的值是不一样的

怎样处理this指向不确定的题目,我们能够用Function.prototype.bind()要领。

myArray = ["zero", "one", "two"];
myBoundMethod = (function (sProperty) {
    console.log(arguments.length > 0 ? this[sProperty] : this);
}).bind(myArray);

myBoundMethod(); // prints "zero,one,two" because 'this' is bound to myArray in the function
myBoundMethod(1); // prints "one"
setTimeout(myBoundMethod, 1000); // still prints "zero,one,two" after 1 second because of the binding
setTimeout(myBoundMethod, 1500, "1"); // prints "one" after 1.5 seconds

运用

1、替代setInterval来完成反复定时
2、防备事宜猖獗触发
3、IE下从新播放单次gif动画
4、blur事宜延时见效

参考资料

[https://html.spec.whatwg.org/…
[http://imweb.io/topic/56ac67f…
[https://developer.mozilla.org…
[http://www.cnblogs.com/suspid…
[https://johnresig.com/blog/ho…
[http://www.cnblogs.com/snandy…
[http://www.ruanyifeng.com/blo…
[http://www.cnblogs.com/silin6…

文章地点:[http://17biu.cn/2017/07/18/se…

    原文作者:17biu
    原文地址: https://segmentfault.com/a/1190000010250793
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞