第四章 變量、作用域和內存問題
1. ECMAScript變量可能包含兩種不同數據類型的值:基本類型值和引用類型值。基本類型指的是簡單的數據段,而引用類型值指那些可能由多個值構成的對象。基本數據類型是:Undefined、Null、Boolean、Number和String。引用類型的值是保存在內存中的對象。JavaScript不允許直接訪問內存中的位置,即不能直接操作對象的內存空間。
2. 不能給基本類型的值添加屬性,只能給引用類型值動態地添加屬性。
3. 從一個變量向另一個變量複製基本類型值時,兩個變量可以參與任意操作而不會相互影響,但從一個變量向另一個變量複製引用類型值時,兩個變量實際上將引用同一個對象,即改變某一個變量,可就會影響另一個變量。
4. ECMAScript中所有函數的參數都是按值傳遞的,即把函數外部的值複製給函數內部的參數,就和把值從一個變量複製到另一個變量一樣。
5. 在檢測引用類型的值時,typeof操作符用處不大,要確定是什麼類型的對象,則使用instanceof操作符,語法如下:
Result = variable instanceofconstructor
所有引用類型的值都是Object的實例,在檢測一個引用類型值和Object構造函數時,instanceof操作符始終會返回true,使用instanceof操作符檢測基本類型的值,則始終返回false,因爲基本類型不是對象。
6. 執行環境定義了變量或函數有權訪問的其他數據,每個執行環境都有與之關聯的變量對象,在Web瀏覽器中,全局執行環境被認爲是window對象。每個函數都有自己的執行環境。當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈(scope chain),作用域鏈的用途,是保證對執行環境有權訪問的所有變量和函數的有序訪問。作用域的前端,始終都是當前執行的代碼所在環境的變量對象。例如當環境是函數時,活動對象最開始只包含了一個變量,即arguments對象(這個對象在全局環境中是不存在的。)全局執行環境的變量對象始終都是作用域鏈中的最後一個對象。
7. 內部環境可以通過作用域鏈訪問所有的外部環境,但外部環境不能訪問內部環境中的任何變量和函數。
8. 延長作用域鏈的兩種方法:try-catch語句的catch塊和with語句。
9. JavaScript沒有塊級作用域,但在JavaScript中,if語句中的變量聲明會將變量添加到當前的執行環境,另外,由for語句創建的變量i即使在for循環執行結束後,也依舊會存在於循環外部的執行環境中。
10. 使用var聲明的變量會自動被添加到最接近的環境中,在函數內部,最接近的環境就是函數的局部環境;在with語句中,最接近的環境是函數環境。如果初始化變量時沒有使用var聲明,該變量會自動被添加到全局環境。
11. 在查找標識符的過程中,如果局部環境中存在着同名標識符,就不會使用位於父環境中的標識符。
12. JavaScript具有自動垃圾收集機制,原理是在按照固定的時間間隔找出那些不再繼續使用的變量,然後釋放其佔用的內存。第一種垃圾收集方式是標記清楚(mark-and-sweep),當變量進入環境時,就將這個變量標記爲“進入環境”,當變量離開環境時,則將其標記爲“離開環境”。該種方式被多種瀏覽器支持。另一種不太常見的垃圾收集策略是叫做引用計數。引用計數的含義是跟蹤記錄每個值被引用的次數。當這個值的引用次數變成0時,則說明沒有辦法在訪問這個值了,因而就可以將其佔用的內存空間回收回來。
13. 分配給Web瀏覽器的可用內存數量通常要比分配給桌面應用程序的少,這樣做的目的主要是出於安全方面的考慮,是爲了防止運行JavaScript的網頁好進全部系統內存而導致系統崩潰。一旦數據不再用,最好通過將其設置爲null來釋放其引用,此做法叫做解除引用,適用於大多數全局變量和全局對象的屬性。解除引用的真正作用是讓值脫離執行環境,以便垃圾收集器下次運行時將其收回。