1. 程式人生 > >JS效能優化——setTimeout()學習筆記

JS效能優化——setTimeout()學習筆記

在最近接觸到的程式碼中,遇到了一個在angularJs中使用setTimeout的問題。就是在setTimeout中對scope中的屬性進行修改,修改後的值不會立即更新到檢視上。

setTimeout()主要用於推遲指定時間後處理相應的函式。在說setTimeout()之前,先要了解JS的執行緒。  

我以前只知道JS執行是“”單執行緒”的,但對執行緒這東西一直沒概念(還為單執行緒怎麼還有非同步方法這個問題揪心過)。最近查了一下,才總算明白了點。

首先,單執行緒的是指js只能在一個執行緒上執行,也就說,js在一個時間裡只能執行一個js任務。js是單執行緒的,js引擎執行緒是有多個,一個主執行緒,其它的後臺配合主執行緒。其中,js引擎裡面有一個訊息佇列,裡面放著各種需要當前程式處理的訊息。

Js要執行的任務主要分為同步任務和非同步任務。其中,同步任務會放在主執行緒中排隊執行,而非同步任務會放入訊息佇列排隊,不會放到主執行緒中。

 

JS的執行過程大致如下:

(1)同步任務都放到主執行緒上執行,瀏覽器會按順序處理主執行緒中的任務。

(2)主執行緒之外,還存在一個“任務佇列”。只要非同步任務有了執行結果,就在“任務佇列”之中放置一個事件。 

(3)一旦“執行棧”中的所有同步任務執行完畢,系統就會讀取“任務佇列”,看看裡面有哪些事件。那些對應的非同步任務,於是結束等待狀態,進入執行棧,開始執行。 

(4)主執行緒不斷重複上面的第三步。

    Js的事件迴圈(Event Loop)大概就是指主執行緒執行完當前任務後讀取任務列表的迴圈過程。

    回到setTimeout()上,這個和非同步任務的執行時一樣的。當過了指定時間之後,所設定的函式就會加入訊息佇列中,若當前無其他任務執行,則這個函式就得到執行機會;否則,要先等主執行緒上的同步任務和在訊息佇列中排前面的任務執行完畢,它才能夠得到執行機會。而這個要被執行的函式會被全域性物件呼叫。這就是我一開始遇到的問題的原因,被執行的函式會被全域性物件呼叫,於是AngularJs無法做出及時的更新,需要在裡面新增$apply來進行手動更新。

對於setTimeout的使用,網上的經典例子如下:

因為setTimeout()是非同步的,所以上面會進入死迴圈。

另外,如果setTimeou()裡面傳遞字串作為執行引數,例如:

此時,他將會呼叫eval()去執行這段程式碼,裡面的字串程式碼將會在全域性環境下執行,上面setTimeout()執行的將會是全域性的a()函式,而不是b()裡面的a()。