读《你不知道的JavaScript》——对象不变性

186 阅读1分钟

我们知道,ES6引入的const是用来定义常量的,对于基本数据类型来说,变量存储的是数据的值,所以用起来没问题,但当我们使用const定义一个数组或者对象时,由于存储的是对象的地址,所以即使我们修改了对象的某一键值,或者为数组增加、删除一项,它的存储地址,所以依旧是常量,这有时候不是我们想要的。

那么要如何定义一个“真正”的对象类型的常量呢?

使用对象的属性描述符

使用configurable: falsewritable: false创建一个常量属性(不可修改、重定义或删除)

var myObj = {};
Object.defineProperty(myObj, 'a', {
  value: 1,
  configurable: false,
  writable: false
})

禁止扩展

禁止一个对象添加新的属性。原有的属性可以修改可以使用delete删除。

var myObj = {a: 2};
Object.preventExtensions(myObj);
myObj.b = 3;
myObj.b; // undefined
myObj.a = 3;
myObj.a; // 3
delete myObj.a // true

密封

Object.seal:创建一个“密封”的对象,实际上是在现有的对象上调用Object.preventExtensions(..)并把所有的现有属性标记为configurable: false

密封之后,不能添加新属性,也不能重新配置或删除任何现有属性,但是可以修改现有属性的值。

var obj = { a: 2 };
Object.seal(obj);
obj.b = 1;
obj.b // undefined
Object.defineProperty(obj, 'a', {
    configurable: true
}) // Uncaught TypeError: Cannot redefine property: a
obj.a = 3
obj.a // 3

冻结

Object.freeze(..)创建一个冻结对象,实际上是在现有的对象上调用Object.seal(..)并把所有的“数据访问”属性标记为writable: false,这样就无法修改属性的值。这个方法是级别最高的不可变性。

Object.freeze(obj)
obj.a = 4
obj.a // 3