setTimeout()中容易忽視的要點

setTimeout語法:瀏覽器

var timeoutId = scope.setTimeout(function[, delay, param1, param2....]); 
var timeoutId = scope.setTimeout(function[, delay]); 
var timeoutId = scope.setTimeout(code[, delay]);
複製代碼

setTimeout要點一:安全

setTimeout第一個參數能夠是一個函數,也能夠是一個包含Javascript代碼的字符串(能夠類比eval()中使用字符串)閉包

//方式1:通常的書寫方式
setTimeout(function(){
	console.log(a)
},1000)

//方式2:也可使用字符串
setTimeout("console.log(a)",1000);
複製代碼

不過,不推薦方式2,不管是代碼可讀性,仍是MDN的官方解釋-安全緣由,亦或是在舊版瀏覽器中的性能緣由~~。函數


setTimeout要點二:性能

Javascript是一個單線程的解釋器,所以一段時間只能執行一段代碼,因此會有Javascript任務隊列,這些任務會按照它們隊列的順序執行。而setTimeout的第二個參數-delay告訴Javascript再過多久把當前任務添加到隊列中。ui

若是省略該參數,delay取默認值0。實際的延遲時間可能會比 delay 值長【一般是因爲函數嵌套致使(嵌套層級達到必定深度),或者是因爲已經執行的setInterval的回調函數阻塞致使】。this

根據HTML5 spec 中精確的數值,delay延遲時間大於等於4ms,即使你把delay設爲0spa


setTimeout要點三:prototype

setTimeout可選參數:附加參數,一旦定時器執行,它們會做爲參數傳遞給function 或 執行字符串(setTimeout參數中的code)。線程

setTimeout(function(param1,param2){
	console.log(param1)   //a
	console.log(param2)   //b
},1000,'a','b')
複製代碼
function timeout(ms) {
	return new Promise((resolve, reject) => {
		setTimeout(resolve, ms, 'finish');
	});
}

timeout(100).then((value) => {
	console.log(value);		//finish
});
複製代碼

setTimeout要點四:

setTimeout都是在全局做用域下執行的,所以函數中的this都是指向window對象(通常狀況下,排除使用ES6中的箭頭函數、Function.prototype.bind()、閉包重寫做用鏈對象。。。。等等更改做用域的其餘方式)

var obj = {
	timer:function(){
		setTimeout(function(){
			console.log(this == window)     //true
		})
	}
}
obj.timer()
複製代碼

雖然有很多的書上/文檔中寫着,嚴格模式下,this是undefined.

BUT,在嚴格模式下,setTimeout( )的回調函數裏面的this仍然默認指向window對象, 並非undefined

"use strict";
setTimeout(function(){
	console.log(this == window)    //true
})
複製代碼