2010-03-02 284 views
12

我想使對象的結構不可變,從而防止它的屬性被替換。但是,這些屬性需要可讀。這可能嗎?有什麼辦法可以防止替換JavaScript對象屬性?

我確定沒有語言功能(沿着Java中的final和C#中的readonly)來支持這一點,但是想知道是否有其他機制可以實現相同的結果?

我在找東西沿着這些路線:

var o = { 
    a: "a", 
    f: function() { 
     return "b"; 
    } 
}; 

var p = o.a;  // OK 
o.a = "b";   // Error 
var q = o.f();  // OK 
o.f = function() { // Error 
    return "c"; 
}; 

回答

14

ECMAScript 5將有seal()freeze(),但沒有好的方法來做到這一點與當前的JavaScript實現。

Source

+1

+1:'' freeze()'聽起來像我以後的事情。 –

+0

你正在運行版本5?! – mkoryak

+1

我剛纔提到它僅供參考。我不積極地對ECMAScript 5編程。 – EndangeredMassa

9

你能做的最好的事情是躲閉包內的性能。

var getMap = function(){ 
    var hidden = "1"; 
    return { 
    getHidden : function() { return hidden; } 
    } 
} 

var f = getMap(); 

alert(f.getHidden()); 

我捅了一下。在上面的代碼中,您將不僅需要返回隱藏,而且還可以將其複製到一個新對象中。也許你可以使用jQuery的擴展爲你做這個,所以你將返回一個新的對象,而不是參考。這可能是完全錯誤的,雖然=)

+0

我需要的屬性是從對象(問題更新,以反映)外部訪問。 –

+0

@Mthethew所以創建一個公共訪問函數。看到我的答案。 –

+0

編輯答案就像你想要的 – mkoryak

4

正如mkoryak說,你可以創建一個封閉隱藏屬性

function Car(make, model, color) { 
    var _make = make, _model = model, _color = color; 

    this.getMake = function() { 
     return _make; 
    } 

} 

var mycar = new Car("ford", "mustang", "black"); 

mycar.getMake(); //returns "ford" 
mycar._make; //error 
+0

如果mkoryak已經說過,爲什麼要重複它? – Zecc

+1

@Zecc因爲那個答案本來沒有代碼樣本 –

5

中的對象的構造函數使用var將創建一個私有變量。這實質上是一個封閉。然後你可以創建一個公共函數來訪問/修改它。 Douglas Crockford在Private Members in Javascript上提供更多信息和示例。

+1

但是你可以替換函數來返回你想要的任何東西。 – EndangeredMassa

+0

@Sean當然,它可以被刪除/替換,但它不能被改變。我想底線是,沒有辦法用可以直接訪問私有變量的東西替換該函數。 –

4

好的,所以已經有了幾個答案,建議你用幾個getter方法返回一個對象。但是你仍然可以替換這些方法。

有這個,這稍微好點。如果不完全替換功能,您將無法替換對象的屬性。但它仍然不是你想要的。

function Sealed(obj) { 
    function copy(o){ 
     var n = {}; 
     for(p in o){ 
      n[p] = o[p] 
     } 
     return n; 
    } 
    var priv = copy(obj); 
    return function(p) { 
     return typeof p == 'undefined' ? copy(priv) : priv[p]; // or maybe copy(priv[p]) 
    } 
} 

var mycar = new Sealed({make:"ford", model:"mustang", color:"black"}); 

alert(mycar('make')); // "ford" 
alert(mycar().make); // "ford" 

var newcopy = mycar(); 
newcopy.make = 'volkwagen'; 
alert(newcopy.make); // "volkwagen" :(

alert(mycar().make); // still "ford" :) 
alert(mycar('make')); // still "ford" :) 
2

您現在可以強制凍結單個對象屬性,而不凍結整個對象。你可以用Object.defineProperty和參數writable: false

var obj = { 
    "first": 1, 
    "second": 2, 
    "third": 3 
}; 
Object.defineProperty(obj, "first", { 
    writable: false, 
    value: 99 
}); 

在這個例子中做到這一點,現在obj.first有其價值鎖定在99

相關問題