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

有没有办法防止替换JavaScript对象属性?,javascript,immutability,final,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

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

我确信没有任何语言特性(如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"; 
};

最好的方法是将属性隐藏在闭包中

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

var f = getMap ();

alert(f.getHidden());

我试了一下。在上面的代码中,您不仅需要返回hidden,还需要将其复制到一个新对象中。也许您可以使用jquery的extend来完成这项工作,这样您将返回一个新对象,而不是引用。虽然=)

ECMAScript 5将具有
seal()
freeze()
,但这可能是完全错误的,但是对于当前的JavaScript实现,没有好的方法可以做到这一点


.

正如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

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

好的,已经有一些答案建议您使用几个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" :)

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

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

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

我需要从对象外部访问属性(问题更新以反映)。@Matthew因此创建一个公共访问函数。请看我的答案。@ivan:这不是4chan,不要粗鲁。这是我最喜欢的使对象不可变的方法,因为客户端编程人员无法访问底层变量。然而,它不是100%安全的,因为我们总是可以从它继承并重写getter(这里我非常缺少Java final方法)。。。。如果hidden={“key”:“value”}。。。您仍然可以修改它的内容。。但是你不能重新分配它。。。但这并不意味着它是一成不变的。。。但是,它的行为方式与Java中的final相同,但这不是不变的、不可更改的……但是您可以替换该函数以返回您想要的任何内容。@Sean确定可以删除/替换它,但不能更改它。我想底线是,没有办法用能够直接访问私有变量的东西来替换函数。我刚才提到它只是为了参考。我没有主动针对ECMAScript 5进行编程。@Zecc,因为该答案最初没有代码示例