從瀏覽器(chrome)進程機制的分析到JavaScript 運行機制之一:瀏覽器多進程還是多線程?

瀏覽器(chrome)進程機制:

瀏覽器作爲一個軟件,大家有沒有好奇瀏覽器是多進程的還是多線程的?每打開一個瀏覽器頁面代表着是一個線程還是一個進程呢?

其實瀏覽器是一個多進程軟件,從開發的角度來說,相對安全的,多線程意味着大家都在'一條船上',你打開蘋果的官網和三星的官網,蘋果官網的頁面崩潰了,三星的頁面也要和你崩潰嗎?無論開發者如何做多線程隔離,線程安全等等操作,整體效果沒有多進程來的安全和穩定的。一般來說一個頁面是一個進程,某些瀏覽器會做優化例如你打開同一個網址。

下面我以chrome瀏覽器來分析其運行機制:

首先我們打開chrome的進程管理器,打開瀏覽器,按下shift+esc即可,或者如圖所示More Tools->Task Manager

 就出現這個Task Managerc窗口了

 

browser進程:瀏覽器的主進程,負責界面的顯示,用戶交互,子進程的管理,提供存儲等功能

GPU Process:GPU進程,負責繪製 repaint 重繪後的 UI 界面

Utility Network:網絡進程,負責頁面網絡資源的加載

插件進程:有插件會顯示插件進程

render進程:內核進程,前端工程師開發和關注的界面,我們用戶開發的進程就是在裏面跑的

 

JavaScript 運行機制:

1.JavaScript是單線程的語言

原因:這樣不僅高效率還安全。當你使用js對DOM,一個進行增加節點操作,另一個進行刪除節點的操作。多線程的話會使瀏覽器的效率降低。多線程必然會引入的鎖,信號量的一類操作,大大增加了複雜性。而瀏覽器是最貼近用戶體驗的一種軟件,用戶需要的是快!快!簡單!簡單!JavaScript設置成單線程是符合工程應用的

延伸:我們需要了解的是進程,線程,或者纖程(協程),這些都是基於操作系統的概念,不是某個語言的特點。在沒有操作系統的下的編程是沒有進程,線程這個說法的。例如C語言,你在Windows或者linux下的編程,有進程,線程這種說法。然而在stm32,c51/c52這種沒有操作系統的環境下編程,是沒有進程,線程這種說法的。

2.任務隊列

單線程就意味着所有事情任務要一個個來,排隊來。JavaScript把這種任務分成兩種了一個是同步任務(synchronous),另一個是異步任務(asynchronous)。同步任務是在主線程上排隊執行的任務,執行完一個任務才能執行下一個任務。異步任務是指不進入主線程,而是進入“任務隊列”,只有“任務隊列”會通知某個異步任務可以執行了才能執行,該任務會進入主線程執行

例子:

<!DOCTYPE html>

<html>
    <head>
        <script>
            console.log(11111)
            setTimeout(function(){
                console.log(2222)
            })
            console.log(333)
        </script>
    </head>
</html>

這裏打印的結果會是:11111 333 2222

因爲setTimeout是異步的,會進入“任務隊列”,等同步任務console執行完了。才通知異步任務

同步任務執行完之前是不會執行異步任務的

例子:

<!DOCTYPE html>

<html>
    <head>
        <script>
            console.log(11111)
            
            setTimeout(function(){
                console.log(2222)
            })
            while(1){}
           // console.log(333)
        </script>
    </head>
</html>

輸出結果是:11111,不會輸出2222的,因爲同步任務while(1)沒有執行完,不會執行異步任務setTimeout的。

同步任務是一個一個執行的,前一個執行完,纔到下一個執行。

<!DOCTYPE html>

<html>
    <head>
        <script>
            console.log(11111)
            /*
            setTimeout(function(){
                console.log(2222)
            })
            */
            while(1){}
            console.log(333)
        </script>
    </head>
</html>

輸出的結果是:11111,不會輸出333,因爲同步任務while(1)沒有執行完

3.深入理解Event Loop

異步執行的運行機制如下:

(1)所有同步任務會在主線程形成一個執行棧。

(2)主線程之外的任務隊列只要有異步的運行結果,就在任務隊列中放置一個事件

(3)執行棧中的同步任務執行完畢,系統會讀取任務隊列開始執行。

(4)主線程不斷重複上面三個步驟

故JavaScript的運行機制:主線程從任務隊列中不斷循環讀取事件,這種稱之爲事件循環(EventLoop),只要主線程空了就會讀取任務隊列。

參考文章:https://baijiahao.baidu.com/s?id=1615713540466951098&wfr=spider&for=pc

4.哪些屬於異步任務

一般有四種:

1.setTimeout和setInterval

2.DOM事件

3.ES6中的Promise

4.Ajax異步請求

說明即使是異步任務也分優先級,分爲微任務和宏任務,微任務的優先級高於宏任務優選執行

微任務:setTimeout

宏任務:setInterval

 

再說說JavaScript的運行過程:

1.語法分析,js會檢查你是否會有語法錯誤這種低級錯誤,每個語言都會有這一步

2.預解析:將函數聲明和定義整體提前,就是說在一個域內說不管你函數定義在前面,中間,後面,都會把你的函數整體提升到最前面。將變量的的聲明整體提前,定義不提前。就是說在一個域內說不管你變量定義在前面,中間,後面,都會把你的變量聲明提升到最前面,注意定義不提前。總結:函數定義整體提升,變量定義變量聲明提升

3.找到函數的形參,將形參和實參統一

4.執行---從上到下執行(按照js運行機制)

 

函數定義整體提升,變量定義變量聲明提升

舉例:

<!DOCTYPE html>

<html>
    <head>
        <script>
            
            console.log(test)
            
            function test(){
                console.log('函數')
            }
        </script>
    </head>
</html>

雖然是在後面定義了函數,但是函數定義整體提升,js會放在前面解析,所以輸出能看到test是個函數,而不是undefined之類的。

<!DOCTYPE html>

<html>
    <head>
        <script>
            
            console.log('a:'+a)

            var a = 10
        </script>
    </head>
</html>

變量定義,聲明整體提升,所以a輸出的是undefined,就是說a是聲明瞭,卻沒有定義。(若沒有聲明會報錯的,不會輸出undefined)

 

總結:

js在瀏覽器(chrome)的render進程裏面跑,js是單線程語言,js運行機制有同步任務和異步任務之分

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章