被遗忘在角落的Object.seal方法

284 阅读2分钟

说起Object.seal之前,我们先来我们先来看下一个概念,属性描述对象: descriptor, 其拥有共有value、configurable、enumerable、value、writable、get、set等6个属性值,感兴趣可以了解下往期文章;

Object.getOwnPropertyDescriptor()

指定对象上一个自有属性对应的属性描述符

  • 来看看它描述了一个什么对象
const obj = { name: "min" };
const descriptor =  Object.getOwnPropertyDescriptor(obj,"name");
// {value: "min", writable: true, enumerable: true, configurable: true}

看到writable:重新赋值属性为true, enumerable:枚举属性为true, configurable:配置属性为true

Object.seal()

我们来看看它到底是一个什么方法,先看下定义

封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

  • 看个例子
const obj = { name: "min" };
Object.defineProperty(obj, "age", {
    value: 23  // writable默认为false
})

const sealObj = Object.seal(obj);
console.log(sealObj === obj) // true
console.log(Object.getOwnPropertyDescriptor(obj, "name")) // {value: "min", writable: true, enumerable: true, configurable: false}
sealObj.say = "hello";  //无效 {name: "min", age: 23}
Object.defineProperty(sealObj, "say", {value: "hello"}) // 报错
delete sealObj.name;  // 无效 {name: "min", age: 23}
sealObj.name = "min123";  // 有效 {name: "min123", age: 23}
sealObj.age = 26;  // 无效 {name: "min123", age: 23}
Object.defineProperty(sealObj, "name", {value: "newName"}) // {name: "newName", age: 23}

新增属性,删除属性,配置属性全部执行失败,但如果已有属性中writable为true,依旧可以被赋值。

  • Object.isSealed(obj): 可判断一个对象是否被密封。

Object.freeze()

和Object.seal()很相似,不过它调用后属性的赋值操作也无法进行,完完全全的无法操作

一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。冻结一个对象后该对象的原型也不能被修改。

const obj = { name: "min" };
const freezeObj = Object.freeze(obj);
console.log(freezeObj === obj)  // true
delete obj.name // 无效  {name: "min"}
obj.age = 23;  // 无效  {name: "min"}
obj.name = "new" // 无效  {name: "min"}
Object.defineProperty(freezeObj, "name", {value: "jdk"})  // 报错

所以冻结对象,freeze更合适, seal留出了已有属性被重新赋值的可能

  • Object.freeze(): 依然可以用于冻结数组
  • Object.isFrozen(obj): 可判断一个对象是否被冻结
  • 如果Object.seal()中属性的writable都为false时,也就是一个冻结对象

Object.preventExtensions()

让一个对象变的不可扩展,也就是永远不能再添加新的属性

const obj = { name: "min" };
const preventObj = Object.preventExtensions(obj);
preventObj.name = "min123";  // {name: "min123"}
preventObj.age = 23;  // 无效
  • Object.isExtensible(): 判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)