js中setTimeout與setInterval
setTimeout和setInterval
javascript都是以單線程的方式運行於瀏覽器的javascript引擎中的,
setTimeout和setInterval的作用只是把你要執行的代碼在你設定的一個時間點插入js引擎維護的一個代碼隊列中
以下方法都是window對象的方法:
setTimeout() 和 clearTimeout()
setInterval() 和 clearInterval()
一、使用時注意範圍
如果需要在對象內部用定時器執行該對象的某一方法時就需要注意了
function Game () {}Game.prototype = {constructor: Game,init: function(){clock = setInterval(function(){ this.update(); }, 500);},update: function(){console.log("test");}}var game = new Game();game.init();上面的寫法會出現 Uncaught TypeError: this.update is not a function
原因就在於 setInterval()屬於window對象的方法,這裡的this指代的是window對象,
而在window對象中又沒有定義update方法,因此會報錯
function Game () {}Game.prototype = {constructor: Game,init: function(){var that = this;clock = setInterval(function(){ that.update(); }, 500);},update: function(){console.log("test");}}var game = new Game();game.init();這樣寫就沒有任何問題了,var that = this;這句話的意思是用that將Game對象儲存起來,
再執行that.update()方法就沒有任何問題了。
其實下面這樣做也是可以的,只是不好傳參了
function Game () {}Game.prototype = {constructor: Game,init: function(){var that = this;clock = setInterval(that.update, 500);},update: function(){console.log("test");}}var game = new Game();game.init();
另外,使用閉包的方式也是可以的
function Game () {function update(){console.log("test");console.log(this);//window}setInterval(update, 500);}Game();
二、深入解析執行原理
setTimeout(callback, time)會初始化一個計時器,
在指定的時間間隔time毫秒後執行回呼函數callback
setInterval(callback, time)也會初始化一個計時器,
但是它是每隔指定的時間間隔time毫秒後就迴圈執行回呼函數callback。
如果需要連續執行某個方法有以下兩種方式:
如果不希望連續調用產生互相干擾的狀況就用setTimeout()嵌套,
如果希望每隔固定時間精確的執行某個動作就用setInterval()
//1.setTimeout(function() {a();setTimeout(arguments.callee, time);}, time);//2.setInterval(function(){a();}, time);
舉個例子:
假如執行a()方法需要10s,time等於3s,下面來分析一下兩種方式的區別
1.
a()方法執行10s,那麼到第一次執行callback中setTimeout的時間也是10s,執行setTimeout
函數,大概的意思就是給瀏覽器發個訊息,“嗨哥們兒,過3s鐘我要向代碼隊列中插入
a()方法的代碼咯”,又因為callback中setTimeout方法後面並沒有要執行的代碼,因此這3秒
cpu其實處於空閑狀態,於是再過了3s的便開始插入代碼,又因為當前cpu空閑,可以立即執行
a()方法,這時時間已經到了第13s。
因此用這種方式執行一個周期所花的時間為13s
2.
由於time等於3s,按道理來講,在3s,6s,9s時會有新的a()代碼插入到代碼隊列中,
但是因為js引擎只允許有一份未執行的a()代碼,所以真實情況並不是這樣
當在前10s,a()方法正在執行期間,實際上只有3s的時候才會有新的a()代碼插入
到代碼隊列,其它的將被忽略掉。當a()方法10s執行完畢,這時3s時插入的a()方法的代碼都會開始運行。
代碼插入的時間與代碼執行時間其實並沒有什麼關係。
因此用這種方式執行一個周期所花的時間為10s
當然,這裡順便說一句,一個函數執行的時間其實並不是固定的,每次執行時間都會
有些偏差,只是大概穩定在某一個值附近罷了,這與cpu內部運行策略有關,這裡扯遠了