2010-03-02 213 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

相关问题