JS學習筆記整理二 變量、做用域和內存問題

變量、做用域和內存問題

基本類型和引用類型

基本類型和引用類型的區別。對保存對象的變量進行復制,操做的是對象的引用。可是添加對象的屬性,操做的就是實際的對象。基本類型沒法動態添加屬性。這裏涉及到昨天說的包裝對象的問題。基本類型是存在棧內存中的。引用類型是存在堆內存,其在堆內存的地址存在棧內存。javascript

Ecmascript中全部函數的參數都是按值傳遞的,而不是引用。即使是做爲引用類型的對象,其實也是值傳遞。雖然在函數內修改對象的屬性會反映到實際的對象中。但重寫形參,並不會反映到原始的引用。(紅皮書71p證實)由於是值傳遞,形參保存的是對象的引用地址,所以重寫形參必然會斷開與原始對象的聯繫。前端

檢測類型,以前學到typeof,能夠很方便的檢測出number,string,boolean,undefined。可是null會檢測爲object。這是針對基本類型,可是不少時候咱們須要查看的是對象的類型。這時候須要用instanceof操做符。和typeof同樣也是關鍵字哦,因此不須要駝峯寫法。java

變量 instanceof 類型    //結果返回布爾值。
複製代碼

執行環境及做用域

執行環境也叫執行上下文。每一個執行環境都對應一個變量對象variable object。編程

var color="blue";
function changecolor(color){
    color="orange";
}
changecolor(color);
console.log(color);//blue
 

var color="blue";
function changecolor(){
    color="orange";
}
changecolor();
console.log(color);//orange
複製代碼

做用域鏈永遠都是從內而外的搜索,永遠都是單向、線性的。瀏覽器

延長做用域鏈

with和try-catch能夠延長做用域鏈。框架

function buildUrl(){
    var qs = "?debug=true";
    with(location){
        var url = href + qs;
    }
    return url;
}
console.log(buildUrl());
複製代碼

try-catch塊中dom

try{
    doSomething();
}catch(ex){
    alert(ex.message); //做用域鏈在此處改變
}
複製代碼

在發生異常進入catch代碼段時。異常對象被推入新的變量對象並置於做用域鏈最前端。而catch代碼段內的局部變量則進入到下一個執行環境的變量對象中。所以,catch內的代碼量較多時性能會降低。解決的辦法就是委託其餘函數進行處理。如:函數

try{
    doSomething();
}catch(ex){
    handleError(ex); //做用域鏈在此處改變
}
複製代碼

同時,咱們也經過這個例子瞭解了,爲何常說要少用全局變量。由於全局變量在做用域鏈的最後,會形成性能問題。性能

有一個技巧,當屢次引用一個全局變量時,咱們能夠將其先保存爲局部變量,再調用這個局部變量。這也是咱們在一些框架裏常常看到的寫法。ui

沒有塊級做用域

使用var聲明的變量會自動添加到最接近的環境中。因此在with中建立的變量會加入到其函數環境內。而並不像一些文章說的所謂返回

初始化未聲明的變量在嚴格模式會報錯。非嚴格模式會成爲全局變量。

垃圾收集 GC

Javascript有自動垃圾收集機制。

主要的方式是標記清除(mark-and-sweep並列關係)。 當變量進入環境,則標記其「進入環境」,有次標記的變量都是不能釋放的。當其離開環境,則標記其「離開環境」。

不常見的方式是引用計數。引用計數存在一些嚴重的問題,好比循環引用,兩個對象互相引用,致使引用計數永遠不爲0,沒法獲得回收。在ie9之前,dom-js存在內存泄露的問題就是由循環引用引發的。若是想完全回收對象,則能夠斷開引用。即將涉及循環引用的變量賦值null,便可消除。

垃圾收集器是週期運行的,所以肯定垃圾收集的時間間隔很是重要。Ie早期是根據內存分配量的一組閾值運行的,當超過期就啓動。但若是一個腳本自己就須要那麼多,垃圾收集就會頻繁觸發。Ie7之後變爲動態修正閾值。

Javascript有自動垃圾收集機制,通常不用在乎內存分配和回收。可是系統分配給瀏覽器的資源一般比較少,由於擔憂js耗盡全部系統內存致使崩潰。因此在編程時要注意:針對全局變量和全局對象的屬性,在不用的時候主動賦值null。以便垃圾收集下一次回收釋放內存。函數環境的局部變量執行完畢就會自動解除引用。

給不用的變量或屬性主動賦值null,一方面消除循環引用,一方面利於垃圾收集。

紅皮書(js高程)82p的總結很精煉,頗有幫助。

相關文章
相關標籤/搜索