JavaScript对象可以被封闭,这样可以防止添加新属性并删除或重新配置现有属性,但属性仍可写。他们也可以被冻结,这是密封加上所有属性变得不可写。不允许更改现有属性的可扩展对象?
显着缺乏的是能够使现有属性为只读,不可移动,不可配置,同时使对象可扩展。这将有助于防止意外践踏对象的属性,同时允许其他代码扩充其属性。
使用vanilla JavaScript创建这样一个对象的最佳或惯用方法是什么?
JavaScript对象可以被封闭,这样可以防止添加新属性并删除或重新配置现有属性,但属性仍可写。他们也可以被冻结,这是密封加上所有属性变得不可写。不允许更改现有属性的可扩展对象?
显着缺乏的是能够使现有属性为只读,不可移动,不可配置,同时使对象可扩展。这将有助于防止意外践踏对象的属性,同时允许其他代码扩充其属性。
使用vanilla JavaScript创建这样一个对象的最佳或惯用方法是什么?
只需通过对象的属性循环,使每一个不可写和不可配置:
var obj = { "foo": 1, "bar": 3 };
Object.defineProperty(obj, "baz", { set: a=>a });
Object.getOwnPropertyNames(obj).forEach(function(name) {
var desc = Object.getOwnPropertyDescriptor(obj, name);
desc.configurable = false;
// make the property non-writable if it is not an accessor property
if(!desc.set && !desc.get) { desc.writable = false; }
Object.defineProperty(obj, name, desc);
});
注意,这不会使存取器属性由set
和get
方法“不可写”,因为定义可写性的概念不适用于访问者属性 - 存储到访问者属性中运行该设置者。
例如,你可以使用一个getter来设置你的属性,如:
var object = {get property(){return "value"} };
使他们只读的,这意味着你不能改变由分配它的价值了,因为在:
object.property = "other";
因为它没有固定器。因此object.property
将继续返回“值”,但仍可以使用delete
运算符删除“属性”键。
这仍然允许该属性被'Object.defineProperty'覆盖。 –
你不必一路走下去用这个尴尬的Object.definePropertty语法来做到这一点 - (因为正如已经提到的那样,你可以很容易地删除它并指定一个新的)但如果你希望你的属性安全地被意外地分配一个不同的值 - 比给定的语法将会做得更好。 –
如果没有提及,Firefox似乎只会留下“价值”。 – Pointy
@FelixKling是的,我最近了解到'defineProperty'具有定义新属性与修改现有属性的不同行为。尽管现在你已经提到了它,但是我应该添加一个'try' /'catch'来处理一些奇怪的情况 - 显然现有的'set'插槽和'configurable:false'在尝试执行'configure:虚假“。 – apsillers
是啊,注意到现在......我总是被'defineProperty'这个名字弄糊涂了,因为对我来说它表示创建了一个全新的属性(吹掉了所有存在的东西)。 –