有什么办法可以防止 JavaScript 对象属性被替换吗?

发布于 2024-08-23 21:50:33 字数 410 浏览 6 评论 0原文

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

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

I would like to make an object's structure immutable, preventing its properties from being subsequently replaced. The properties need to be readable, however. Is this possible?

I'm sure there are no language features (along the lines of final in Java and readonly in C#) to support this but wondered whether there might be another mechanism for achieving the same result?

I'm looking for something along these lines:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

温柔女人霸气范 2024-08-30 21:50:33

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

来源

ECMAScript 5 will have seal() and freeze(), but there's no good way to do this with current JavaScript implementations.

Source.

苏辞 2024-08-30 21:50:33

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

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

var f = getMap ();

alert(f.getHidden());

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

the best thing you can do is hide your properties inside of a closure.

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

var f = getMap ();

alert(f.getHidden());

I took a stab at it. In the above code you will need to not just return hidden but copy it into a new object perhaps. maybe you can use jquery's extend to do this for you, so you will be returning a new object, not the reference. This may be completely wrong though =)

沉默的熊 2024-08-30 21:50:33

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

Using var in an object constructor will create a private variable. This is essentially a closure. Then you can create a public function to access/modify it. More information and examples available on Private Members in Javascript by Douglas Crockford.

近箐 2024-08-30 21:50:33

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

As mkoryak said, you can create a closure to hide properties

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
浅听莫相离 2024-08-30 21:50:33

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

Okay, so there's been already a couple of answers suggesting you return an object with several getters methods. But you can still replace those methods.

There's this, which is slightly better. You won't be able to replace the object's properties without replacing the function completely. But it's still not exactly what you want.

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" :)
也只是曾经 2024-08-30 21:50:33

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

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

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

You can now force a single object property to be frozen instead of freezing the whole object. You can achieve this with Object.defineProperty and the parameter writable: false

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

In this example, obj.first now has its value locked to 99.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文