2012-12-09 22 views
4

好吧,我嘗試創建新的對象是這樣的:Object.defineProperty獲取/設置封閉

var src = {a:'a', b:'b', c:'c'}; 
var out = {}; 
for(var prop in src){ 
    Object.defineProperty(out, prop,{ 
     get: function(){ 
      return src[prop]; 
     }, 
     set: function(val){ 
      src[prop]=val; 
     } 
    }) 
} 

,並得到一個壞的結果:

out = {a:'c', b:'c', c:'c'} 

我知道其他的方法來創建這個對象,所以爲:

for (var prop in src) { 
    (function(prop) { 
     Object.defineProperty(out, prop, { 
      get: function() { 
       return src[prop]; 
      }, 
      set: function(val) { 
       src[prop] = val; 
      } 
     }) 
    })(prop) 
} 

或:

Object.keys(src).map(function(prop){ 
    Object.defineProperty(out, prop,{ 
     get: function(){ 
      return src[prop]; 
     }, 
     set: function(val){ 
      src[prop]=val; 
     } 
    }) 
}) 

但我不明白爲什麼,在第一個方法中,一個字符串參數「prop」將通過鏈接發送到函數'defineProperty'。請幫助我理解這一點。 對不起,英語不好。

+0

對我來說,你的其他方式也行不通。即使我嘗試指定類似「out.a =」的東西「 ' – nus

+0

我總是仍然是一個空對象我想出了一種方法來製作泛型setters/getters。 [請參閱我的答案](http://stackoverflow.com/a/18043786/1115652)。 – nus

回答

4

當你在一個循環中創建一個函數時,你會在該循環中使用的變量周圍創建一個閉包。在這種情況下,有一個關閉prop。每個函數(獲取者)都有一個對prop的引用,所以當它們稍後被調用時(當使用獲取器時),它們使用prop中的值,這恰好是在循環中分配的最後一個值。

換句話說,因爲稍後調用getter,所以prop中的值是上次設置的值。另一方面,由於沒有關閉,因此獲得了正確的值。它在調用時被調用,而不是在循環完成後調用。

+0

比我更好回答,這是完整的。我無法找到我的話。 – helly0d

+0

嗯,如果我定義get函數,如何爲src [prop]創建閉包但不支持prop? – 3y3

+0

@ 3y3我說最好的方法是在'Object.keys'上使用'map'或'forEach'。 – helly0d