这是我参与8月更文挑战的第二十五天,活动详情查看:8月更文挑战
不变性
有时候我们会希望属性或者对象是不可改变的。在ES5中,可以通过很多种方法来实现,然而所有方法创建的都是浅不变性,也就是说,它们只会影响目标对象和它的直接属性。如果目标对象引用了其他对象(数组、对象、函数等),其他对象的内容是不受影响的,仍然可变。
myImmutableObject.foo;//[1,2,3]
myImmutableObject.foo.push(4);
myImmutableObject.foo;//[1,2,3,4];
假定代码中的myImmutableObject已经被创建并且是不可变的,但是为了保护它的内容myImmutableObjec.foo,还需要使用以下的方法让foo也不可变。
对象常量
结合writable:false和configurable:false就可以创建一个真正的常量属性(不可修改、重定义或者删除):
var myObject={};
Object.defineProperty(myObject,"FAVORITE_NUMBER",{
value:2,
writable:false,
configurable:false
});
禁止扩展
如果需要禁止一个对象添加新的属性并且保留已有的属性,可以用Object.preventExtensions():
var myObject = {
a : 2
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b;//undefined
在非严格模式下,创建b会静默失败,在严格模式下,会抛出TypeError错误。
密封
Object.seal()会创建一个“密封”的对象,这个方法实际上会在一个现有的对象上对应Object.preventExtensions()并且把所有现有的属性标记为configurable:false。 所以,密封之后不仅不能添加新的属性,也不能重新配置或者删除任何现有的属性(但可以修改属性值)
冻结
Object.freeze()会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal并把所有的“数据访问”属性标记为:writable:false,这样就无法修改它们的值。
这个方法是可以应用在对象上的级别最高的不可变性,它会禁止对于对象本身及其任意直接属性的修改(不过还是无法影响到这个对象引用的其他对象)。
“深度冻结”一个对象:先在这个对象上调用Object.freeze(),然后遍历所有它引用的对象,并在这些引用的对象上调用Object.freeze()。但是这样可能会无意中冻结其他共享对象。