我想使对象的结构不可变,防止其属性随后被替换。但是,属性需要是可读的。这可能吗?
我确信没有语言功能(在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";
};
答案 0 :(得分:14)
ECMAScript 5将有seal()
和freeze()
,但目前的JavaScript实施方法没有好办法。
答案 1 :(得分:9)
你能做的最好的事情就是把你的属性隐藏在一个闭包内。
var getMap = function(){
var hidden = "1";
return {
getHidden : function() { return hidden; }
}
}
var f = getMap ();
alert(f.getHidden());
我抓了一把。在上面的代码中,您不仅需要返回隐藏,而且可能将其复制到新对象中。也许你可以使用jquery的扩展为你做这个,所以你将返回一个新对象,而不是引用。这可能是完全错误的但是=)
答案 2 :(得分:5)
在对象构造函数中使用var
将创建一个私有变量。这基本上是一个封闭。然后,您可以创建一个公共函数来访问/修改它。 Douglas Crockford在Private Members in Javascript上提供了更多信息和示例。
答案 3 :(得分: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
答案 4 :(得分: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" :)
答案 5 :(得分:2)
现在可以强制冻结单个对象属性,而不是冻结整个对象。您可以使用Object.defineProperty
和参数writable: false
var obj = {
"first": 1,
"second": 2,
"third": 3
};
Object.defineProperty(obj, "first", {
writable: false,
value: 99
});
在此示例中,obj.first
现在将其值锁定为99。