1. 程式人生 > >深入理解JavaScript特性

深入理解JavaScript特性

事件綁定 引用計數 深入理解 高級 地址 長時間 ava 程序設計 指定

最近在讀《JavaScript高級程序設計》這一本書,裏面提到了JavaScript的特征,倍感興趣,於是結合自己的認識,在這裏進行一下總結。

1、JavaScript的垃圾回收機制

javaScript中的5種數據類型存放在棧中(Undefined、Null、Boolean、Number、String),非基本數據類型存放在堆中,占用內存,堆不會被程序自動釋放。

一張圖看懂JS中數據類型的存放位置:基本數據類型存放在棧中,非基本數據類型存放在堆中(對象),變量obi1在棧中存儲的只是堆中對象的地址。

技術分享

聲明變量a=對象,只是聲明一個指針地址指向存儲該對象的內存空間,每多一個指向同一內存空間的指針地址,該對象的引用計數就會加1。

如果代碼在運行過程中有一個對象不再被需要了,但是引用計數不為零,垃圾回收機制就不能釋放這塊內存,就被稱為內存泄漏。

釋放內存的方法就是 接觸對該內存地址的引用,將引用他的指針地址設置為null,如:a=null;

2、JavaScript 單線程(同一個時間只能做一件事)核心特征

JS除了主線程之外還存在一個任務隊列,(js單線程所有任務必須排隊完成)。

js計算能力很弱如果存在一個耗時較長的任務,後一個任務就必須等待很長時間讓前一個任務執行完畢,,如果是網絡請求他的耗時完全取決於網絡狀況,(Ajax)不符合js設計邏輯。

主線程可以忽略io(input/output)設備,掛起處於等待中的任務(監聽事件綁定的任務,ajax網絡請求)先運行排在後面的任務,,等到io設備有了返回結果,再回過頭把掛起任務執行下去 (異步事件)。

所有任務分兩種synchronous同步事件asynchronous異步事件,在js中:

同步事件在主線程上排隊執行(前一個執行完畢,後一個才能執行)。

異步事件不進入主線程,而進入任務隊列(task queue),只有任務任務隊列通知主線程,某個異步任務可以執行了,該任務才會從任務隊列中取出進入主線程。

3、JavaScript運行機制步驟

(1)所有同步任務都在主線程上依次執行,形成(執行棧)。棧的定義:先進後出,後進先出。

舉個例子:定義三個函數,sayHello函數直接在student函數體內調用,isAdult函數作為參數傳給了sayHello函數,在這裏isAdult也是一個回調函數。

三個函數進入執行棧的順序依次是:student,sayHello,isAdult

        function student(){
            var age = 18;
            var name = 小李
            sayHello(name,age,isAdult(age))
            console.log("student函數")   //最後出棧
        }

        function isAdult(age){
            var result = age >= 18 ? 成年:未成年
            console.log("isAdult函數")   //最先出棧
            return result;
        }

        function sayHello(name,age,reust){
            console.log(hello!This is +name+ +age+years old 我 + reust)
            console.log("sayHello函數")
        }
        student();

看輸出結果:三個函數進入執行棧的順序依次是:isAdult,student,sayHello

技術分享

(2)主線程之外,存在一個任務隊列,只要異步任務有了返回結果,該任務就會被放入任務隊列中。

(3)執行棧中所有任務執行完畢後,就會訪問任務隊列,檢查隊列中有哪些事件,獲取任務隊列中最先等待的事件,讓該事件進入執行棧,開始執行。

(4)不斷重復第三步。

4、JavaScript中回調函數callback(事件綁定函數)

例:綁定點擊事件,當點擊事件觸發時 js會調用事件綁定的函數該函數稱為事件的回調函數(異步任務必須指定回調函數)。

任務隊列 先進先出數據結構,排在前面的事件會先被主線程讀取,所以如果隊列中有‘定時器‘,定時器未必準時觸發,取決於前一個任務隊列中的函數執行的結束。

5、JavaScript中內存區域

程序運行時,需要內存空間存放數據,分別為stack(棧)和heap(堆)。

棧是有結構的,每個區塊按照一定的順序取存放,可以明確的知道每個區塊的大小,而堆是沒有結構的,數據任意存放,因此棧的調用要快於堆。

每個線程分配一個棧,每個進程分配一個堆,stack是線程獨占,heap是線程公用的。

棧是系統自動開辟的自動釋放的, 堆是程序員手動開辟和釋放的。

深入理解JavaScript特性