12

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

我确信没有语言特性(final在 Java 和readonlyC# 中)支持这一点,但想知道是否可能有另一种机制来实现相同的结果?

我正在寻找这些方面的东西:

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"; 
};
4

6 回答 6

14

ECMAScript 5 将具有seal()and freeze(),但是对于当前的 JavaScript 实现没有很好的方法来做到这一点。

来源

于 2010-03-02T17:43:34.807 回答
9

你能做的最好的事情就是将你的属性隐藏在一个闭包中。

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

var f = getMap ();

alert(f.getHidden());

我试了一下。在上面的代码中,您不仅需要返回隐藏,还可能需要将其复制到一个新对象中。也许您可以使用 jquery 的扩展来为您执行此操作,因此您将返回一个新对象,而不是引用。这可能是完全错误的=)

于 2010-03-02T17:40:50.770 回答
5

在对象构造函数中使用var将创建一个私有变量。这本质上是一个闭包。然后您可以创建一个公共函数来访问/修改它。Douglas Crockford的 Javascript 中的 Private Members提供了更多信息和示例。

于 2010-03-02T17:44:50.360 回答
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
于 2010-03-02T17:44:41.620 回答
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" :)
于 2012-03-06T22:01:48.910 回答
2

您现在可以强制冻结单个对象属性,而不是冻结整个对象。Object.defineProperty您可以使用和 参数来实现这一点writable: false

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

在此示例中,obj.first现在将其值锁定为 99。

于 2016-10-20T01:57:33.123 回答