1. 程式人生 > 其它 >《JavaScript高階程式設計》學習筆記(3)——變數、作用域和記憶體問題

《JavaScript高階程式設計》學習筆記(3)——變數、作用域和記憶體問題

歡迎關注本人的微信公眾號“前端小填填”,專注前端技術的基礎和專案開發的學習。

本節內容對應《JavaScript高階程式設計》的第四章內容。

1、函式:通過函式可以封裝任意多條語句,而且可以在任何地方、任何時候呼叫執行。ECMAScript中的函式用function關鍵字來進行宣告,後面跟一組引數以及函式體。不必指定是否有返回值

 function functionName(args0,args1,...argsN){
      //statements       
 }

 2、函式的過載:為一個函式編寫兩個定義,只要這兩個定義的簽名(接受的引數的型別和數量)不同即可。ECMAScript函式沒有簽名,因為其引數是由包含零個或多個值得陣列來表示的,而沒有函式簽名,真正的過載是不可能做到的。如果在ECMAScript中定義兩個名字相同的函式(函式名和引數的個數均相同),則該名字只屬於後定義的函式。

function add(num){
     return num + 100 ;   
}

function add(num){
     return num + 200 ;   
}

var result = add(100) ;   //300

3、JavaScript變數鬆散型別的本質決定了它至少在特定時間用於儲存特定值的一個名字而已,由於不存在定義某個變數必須儲存何種資料型別值得規則,變數的值及其資料型別可以在指令碼的生面週期內改變。

4、ECMAScript變數包含兩種不同的資料型別:基本型別值和引用型別值。基本型別值指的是簡單的資料段,引用型別值指那些可能由多個值構成的物件。注意:在JavaScript中字串是基本型別,是按值訪問的,這一點與java中的不一樣。

對於引用型別的值(即物件),我們可以動態地為其新增屬性和方法:

var person = new Object() ;
person.name = "Jack" ;  //新增屬性name

5、變數值的複製:

  • 對於簡單型別值:複製前後的兩個變數沒有任何關係,某一個變數的改變並不影響另一個變數的值
  • 而對於引用型別值:複製的內容實際上是一個指標,指向該物件的儲存地址,所以複製前後的兩個變數實際上指向同一個物件,某一個變數的值的改變會影響另一個變數的值。

6、ECMAScript中所有函式的引數都是按值傳遞的,即將函式外部的值複製給函式內部的引數,就和把值從一個變數複製到另一個變數一樣,應用型別的複製實際上是物件的儲存地址的複製。

7、前面提到檢測變數的資料型別用typeof,但是typeof的返回值只有string、number、boolean、undefined、function(函式和正則表示式均返回function)、object(null和引用型別均返回object)。所以,對於引用型別或null,我們無法具體確定是屬於哪一種引用型別的物件。要確定屬於哪一種引用型別,我們可以用instanceof操作符,如果變數是給定引用型別的物件,則instanceof操作符將返回true。因此,在檢測一個引用型別值和object建構函式時,始終會返回true,而如果使用instanceof操作符檢測基本型別的值,則該操作符始終會返回false,因為基本型別不是物件。

8、在javascript中,執行環境定義了變數或函式有權訪問的其他資料型別,決定了他們各自的行為。每個執行環境都有一個與之關聯的變數物件,環境中定義的所有變數和函式都儲存在這個物件中

  • 根據ECMAScript實現所在的宿主環境不同,表示執行環境的物件也不一樣。
  • 某個執行環境中的所有程式碼執行完畢後,該環境就被銷燬,儲存在其中的所有變數和函式定義也隨之銷燬。
  • 全域性執行環境是最外圍的一個執行環境。在web瀏覽器中,全域性執行環境被認為是window物件,因此所有全域性變數和函式都是作為window物件的屬性和方法建立的。
  • 每個函式都有自己的執行環境,當執行流進入一個函式時,函式的環境就會被推入一個環境棧中。而在函式執行完畢後,棧將其環境彈出,把控制權返回給之前的執行環境。
  • 當代碼在一個環境中執行時,會建立變數物件的一個作用域鏈(scope chain)。作用域鏈的作用是保證對執行環境有權訪問的所有變數和函式的有序訪問。作用域鏈的前端始終都是當前執行的程式碼所在環境的變數物件。作用域鏈的下一個變數物件來自包含環境,再下一個變數物件則來自下一個包含環境。這樣一直延續到全域性執行環境,全域性執行環境的變數物件始終是作用域鏈中的最後一個物件。
  • 識別符號的解析是沿著作用域鏈一級一級地搜尋識別符號的過程。搜尋過程始終從作用域鏈的前段開始,然後逐級地向後回溯,直至找到識別符號為止(如果找不到識別符號,通常會導致錯誤發生)。
  • 當執行流進入到try-catch語句的catch語句或者with語句中時,作用域鏈就會得到延長。
  • javascript中沒有塊級作用域。 if(true){ var color = "blue" ; } alert(color) ; //在java中,存在塊級作用域,此時在if外面用到color變數則是不合規範的,但是在javascript中不存在這種問題

9、垃圾收集:javascript具有自動垃圾收集機制,也就是說,執行環境會負責管理程式碼執行過程中是用得記憶體。這樣,在編寫javascript程式時,我們不需要關心記憶體使用問題,所需記憶體分配以及無用記憶體的回收完全實現了自動管理。則也解決了C++/C語言存在的很大一部分問題。對於垃圾收集,通常用到兩種策略來判斷一個變數是否是垃圾:

  • 標記清除(mark-and-sweep):當變數進入環境時,就將該變數標記為進入環境,當變數離開環境時,標記為離開環境。
  • 引用計數(reference counting):一個變數被引用(賦值給另一個變數)一次則應用數加1,相反,如果包含該物件應用的變數又取得了另外一個值,則減1。當一個變數計數為0時,表示該變數不再需要,可以清除了。注意迴圈引用的情況會導致變數無法被清除。

10、確保佔用最少的記憶體可以讓頁面獲得更好的效能。而優化記憶體佔用的最佳方式,就是為執行中的程式碼只儲存必要的資料。一旦資料不再用,最好通過將其值設定為null來釋放其引用(這個方法叫解除引用)。