有没有办法阻止替换JavaScript对象属性?

时间:2010-03-02 17:40:10

标签: javascript immutability final

我想使对象的结构不可变,防止其属性随后被替换。但是,属性需要是可读的。这可能吗?

我确信没有语言功能(在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"; 
};

6 个答案:

答案 0 :(得分:14)

ECMAScript 5将有seal()freeze(),但目前的JavaScript实施方法没有好办法。

Source

答案 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。