2011-06-13 77 views
8

我對JavaScript有些新鮮感,所以請耐心等待,如果這是一個愚蠢的問題。關於JavaScript中封閉/封裝效率的問題

比方說,我有一個「類」,看起來像這樣:

var obj = function() { 
    var val; 
    return { 
     setVal: function(newVal) { 
      val = newVal; 
     }, 
     getVal: function() { 
      return val; 
     } 
    }; 
}; 

假設我的語法是正確的,這定義了一個名爲「私有」屬性的類「價值」與方法設置/獲取物業。現在,我會從這個類創建兩個對象:

var myObj = obj(); 
var yourObj = obj(); 

這是否創建每個對象單獨SETVAL()和GETVAL()方法?如果不是,爲什麼不呢?如果是這樣,在構建高效的Web應用程序時,這是一個嚴重的問在大多數/所有情況下,關閉效率的權衡(如果有的話)是否值得?我是否愚蠢?

感謝, 傑拉德

+0

這裏是關於封閉和原型製作的好文章。 http://www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-closures – ScottE 2011-06-13 14:20:25

+0

這是一個很好的問題來問,如果你只是從JavaScript開始。 – Zoidberg 2011-06-13 15:06:46

回答

0

它不這樣做概念。然而,由於這是一種常見的模式,所以現代JavaScript JITers知道如何優化它,以便存儲在內存中的代碼只有一個副本,並具有適當的指針重定向以使其與相關閉包協同工作。

編輯:雖然我不是真的通過源代碼進行spelunking,這裏有一些基本的證明。 Download the Chrome dev channel release,並採取堆快照之前和運行下面的代碼後:

var obj = /* as above */; 

var objs = []; 
for (var i = 0; i < 10000; ++i) { 
    objs.push(obj()); 
} 

然後爲代碼做同樣的:

function Obj() { } 
Obj.prototype.setVal = function (value) { this._val = value; }; 
Obj.prototype.getVal = function() { return this._val; }; 

var objs = []; 
for (var i = 0; i < 10000; ++i) { 
    objs.push(new Obj()); 
} 

你會發現堆快照顯示「代碼相同的數字「在這兩種情況下,我所描述的優化確實正在進行。

+0

它仍然創建'setVal'和'getVal'方法的兩個實例 – Raynos 2011-06-13 14:14:53

+0

是的,在JavaScript中是正確的。但是沒有效率損失,因爲在現代JIT編譯的機器代碼級別上,每個實例只有一個實例。 – Domenic 2011-06-13 14:20:04

+1

請重新提供鏈接到V8和Jaegermonkey源代碼。我會想象有所有這些函數的多個實例,每個實例都有指向正確的Closure上下文的指針。如果實際上只有兩個函數,那麼作爲一個優化,這真的很讓人印象深刻 – Raynos 2011-06-13 14:23:46

3
var obj = function() { 
    var val; 
    return { 
     setVal: function(newVal) { 
      val = newVal; 
     }, 
     getVal: function() { 
      return val; 
     } 
    }; 
}; 

這個函數的作用是什麼如下:

  • 創建變量命名爲val
  • 創建新的對象
  • 創建一個新的功能,並將其分配給外地setVal
  • 創建一個新的功能並將其分配給字段getVal
  • 返回對象。

所以你總是創造4個新的東西。

如果頁面上的對象少於1000個,這並不是真正的問題。重構它是一個微觀優化。

另一種方法是不依賴局部變量並使用this._val來指示val是私有的。