一行贪、SetTimeout與ClearTimeout
setTimeout()方法設(shè)置一個定時器建瘫,該定時器在定時器到期后執(zhí)行一個函數(shù)或指定的一段代碼。每次定時器到期函數(shù)只執(zhí)行一次殷蛇。
句法
var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);
參數(shù)
function
function是你想要在到期時間(delay
毫秒)之后執(zhí)行的橄浓。
code
這是一個可選語法,你可以使用字符串而不是function在delay
毫秒之后編譯和執(zhí)行字符串 (使用該語法是不推薦的匀们, 原因和使用 [eval()
]一樣准给。eval() 函數(shù)會將傳入的字符串當(dāng)做 JavaScript 代碼進(jìn)行執(zhí)行露氮,是有安全風(fēng)險)。
delay
延遲的毫秒數(shù) (一秒等于1000毫秒)畔规,函數(shù)的調(diào)用會在該延遲之后發(fā)生叁扫。如果省略該參數(shù),delay取默認(rèn)值0沈跨,意味著“馬上”執(zhí)行兔综,或者盡快執(zhí)行。不管是哪種情況涧窒,實際的延遲時間可能會比期待的(delay毫秒數(shù)) 值長锭亏。
param1, ..., paramN
附加參數(shù),一旦定時器到期戴已,它們會作為參數(shù)傳遞給[function
]锅减。
返回值
返回值timeoutID
是一個正整數(shù),表示定時器的編號握联。這個值可以傳遞給clearTimeout
來取消該定時器每瞒。
需要注意的是setTimeout()
和setInterval()
共用一個編號池剿骨。技術(shù)上clearTimeout
和 clearInterval()
可以互換。但是浓利,為了避免混淆荞膘,不要混用取消定時函數(shù)。
因此在同一個對象上(一個window或者worker)淘菩,setTimeout()
或者setInterval()
在后續(xù)的調(diào)用不會重用同一個定時器編號屠升。但是不同的對象使用獨立的編號池。
例子
var myVar;
function myFunction() {
myVar = setTimeout(function(){
alert("Hello")
}, 3000);
}
function myStopFunction() {
clearTimeout(myVar);
}
上述myFunction函數(shù)3秒后alert警告信息汇在,myStopFunction清除定時器脏答。
setTimeout除了做定時器外還能干什么用?
非常多阿蝶,比如說:在處理DOM點擊事件的時候通常會產(chǎn)生冒泡羡洁,正常情況下首先觸發(fā)的是子元素的handler,再觸發(fā)父元素的handler辛蚊,如果我想讓父元素的handler先于子元素的handler執(zhí)行應(yīng)該怎么辦真仲?那就用setTimeout延遲子元素handler若干個毫秒執(zhí)行吧。問題是這個“若干個”毫秒應(yīng)該是多少飞蛹?可以是0灸眼。請看:
(function () {
setTimeout(function () {
alert(2);
}, 0);
alert(1);
})()
會先彈出1,再彈出2霉囚。
setTimeout匕积,setInterval都存在一個最小延遲的問題闪唆,雖然你給的delay值為0,但是瀏覽器執(zhí)行的是自己的最小值票顾。HTML5標(biāo)準(zhǔn)是4ms帆调,但并不意味著所有瀏覽器都會遵循這個標(biāo)準(zhǔn),包括手機瀏覽器在內(nèi)含鳞,這個最小值既有可能小于4ms也有可能大于4ms芹务。在標(biāo)準(zhǔn)中,如果在setTimeout中嵌套一個setTimeout, 那么嵌套的setTimeout的最小延遲為10ms潜必。
不光是上述磁滚,其他任何你想要延遲執(zhí)行的函數(shù)都可以使用SetTimeout()
宵晚。
關(guān)于"this"的問題
查看下面的例子:
let 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
后兩行myArray.myMethod函數(shù)傳遞給 setTimeout,到了定時時間晒他,this沒有指向逸贾,默認(rèn)指向window對象铝侵。并且沒有方法把 thisArg 傳遞給setTimeout。
可能的解決方案:
一個通用的方法是使用包裝函數(shù)
setTimeout(function(){myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 seconds
setTimeout(function(){myArray.myMethod('1')}, 2500); // prints "one" after 2.5 seconds
或者箭頭函數(shù)
setTimeout(() => {myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 seconds
setTimeout(() => {myArray.myMethod('1')}, 2500); // prints "one" after 2.5 second
**注:JavaScript 1.8.5 引入了 Function.prototype.bind()
方法狐赡,該方法允許顯式地指定函數(shù)調(diào)用時 this 所指向的值 疟丙。該方法可以幫助你解決 this 指向不確定的問題享郊。
let 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
二、SetInterval()
句法
intervalID = window.setInterval(function展蒂,delay [温自,param1悼泌,param2,...]);
intervalID = window.setInterval(code隘世,delay);
-
intervalID
是定時器編號, -
function
是必須重復(fù)調(diào)用的[函數(shù)] -
code
在替代語法中复斥,是表示要重復(fù)執(zhí)行的代碼的字符串械媒。 -
delay
是setInterval()
每次調(diào)用前必須等待的毫秒數(shù)(千分之一秒)。如果delay
小于10痢虹,則使用的值將減小為10主儡。
實例:
var y=0;
var x = new Date().getTime();
var d=setInterval(a,500);
function a() {
y++;
sleep(1000);
if(y>=4){
clearInterval(d)
}
console.log(new Date().getTime()-x);
}
function sleep(sleepTime){
var start=new Date().getTime();
while(true){
if(new Date().getTime()-start>sleepTime){
break;
}
}
}
上述控制臺輸出為:
可以看出糜值,setInterval()
函數(shù)并沒有每隔500ms運行一次sleep函數(shù)寂汇。因此使用setInterval()
函數(shù)是有風(fēng)險的。
這里介紹一下荣恐,JS是一個單線程的解釋器累贤,因此一段時間內(nèi)只能執(zhí)行一段代碼。為了要控制執(zhí)行的代碼硼被,就有一個JS任務(wù)隊列渗磅。這些任務(wù)會按照將它們添加到隊列的順序執(zhí)行始鱼。如果函數(shù)執(zhí)行時間過長,setInterval()
函數(shù)間隔時間過短医清,就會導(dǎo)致一些【函數(shù)】被忽略掉会烙。
一般來說筒捺,使用超時調(diào)用是模擬(可以使用遞歸系吭,即自己調(diào)用自己)間歇調(diào)用的一種最佳模式颗品,在開發(fā)環(huán)境下很少用間歇調(diào)用。
參考:https://developer.mozilla.org/zhCN/docs/Web/API/Window/setTimeout
http://www.reibang.com/p/fc9a08ca2c92