注册

freeze、seal、preventExtensions对比

Object常用的方法中,Object.freezeObject.seal对于初学者而言,是两个较为容易混淆的概念,常常傻傻分不清两者的区别和应用场景


概念


先看看两者定义


Object.freeze在MDN中的定义



Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。



Object.seal在MDN中的定义



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



从两者定义可以得到两者差异:Object.freeze核心是冻结,强调的是不可修改。Object.seal核心是封闭,强调的是不可配置,不影响老的属性值修改


差异


定义一个对象,接下来的对比围绕这个对象进行


"use strict";
const obj = {
name: "nordon"
};

使用Object.freeze


Object.freeze(obj);
Object.isFrozen(obj); // true
obj.name = "wy";

使用Object.isFrozen可以检测数据是否被Object.freeze冻结,返回一个Boolean类型数据


此时对冻结之后的数据进行修改,控制台将会报错:Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'


使用Object.seal


Object.seal(obj);
Object.isSealed(obj); // true
obj.name = "wy";

使用Object.isSealed可以检测数据是否被Object.seal封闭,返回一个Boolean类型数据


此时修改name是成功的,此时的obj也成功被修改


注意:若是不开启严格模式,浏览器会采用静默模式,不会在控制台抛出异常信息


共同点


主要以Object.seal演示


不可删除


delete obj.name;

控制台将会抛出异常:Uncaught TypeError: Cannot delete property 'name' of #<Object>


不可配置


可以修改原有的属性值


Object.defineProperty(obj, 'name', {
value: 'wy'
})

不可增加新的属性值


Object.defineProperty(obj, "age", {
value: 12,
});

控制台将会抛出异常:Uncaught TypeError: Cannot define property age, object is not extensible


深层嵌套


两者对于深层嵌套的数据都表现为:无能为力


定义一个嵌套的对象


"use strict";
const obj = {
name: "nordon",
info: {
foo: 'bar'
}
};

对于obj而言,无论是freeze还是seal,操作info内部的数据都无法做到对应的处理


obj.info.msg = 'msg'

数据源obj被修改,不受冻结或者冰封的影响


若是想要做到嵌套数据的处理,需要递归便利数据源处理,此操作需要注意:数据中包含循环引用时,将会触发无限循环


preventExtensions


最后介绍一下Object.preventExtensions,为何这个方法没有放在与Object.freezeObject.seal一起对比呢?因为其和seal基本可保持一致,唯一的区别就是可以delete属性,因此单独放在最后介绍


看一段代码


"use strict";
const obj = {
name: "nordon",
};

Object.preventExtensions(obj);
Object.isExtensible(obj); // false, 代表其不可扩展

delete obj.name;

作者:Nordon
链接:https://juejin.cn/post/7028389571561947172

0 个评论

要回复文章请先登录注册