本文源码基于 React V16.8.6
源码
在 React 和 ReactROM 源码中,xx.development.js 代码都会使用到 Object.seal,主要是对 ref 做属性扩展限制,防止对象的 key 发生变更。
// createRef
export function createRef(): RefObject {
const refObject = {
current: null,
};
if (__DEV__) {
Object.seal(refObject);
}
return refObject;
}
// useRef 相关
function mountRef<T>(initialValue: T): {current: T} {
const hook = mountWorkInProgressHook();
const ref = {current: initialValue};
if (__DEV__) {
Object.seal(ref);
}
hook.memoizedState = ref;
return ref;
}
Object.seal
Object.seal() 方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。
图中,Object.seal 使用之前 configurable 是 true,使用之后变为 false。
这表示 Object.seal 处理后属性无法删除,也不能从数据描述变为存取描述。MDN 属性描述符

更改枚举属性失败。

删除无效

不能把 a 从数据描述变为存取描述,但是可以通过 Object.defineProperty 改变它的 value,等同于 obj.a = '我是a'

如果对象被 Object.seal 处理过,则对象不能扩展和删除属性,尝试扩展一个属性

用 . 号方式扩展属性静默失败,用 Object.defineProperty 扩展则直接报错 Uncaught TypeError: Cannot define property c, object is not extensible,对象不可扩展了。
使用 Object.isSealed 判断对象是否被 Object.seal 处理。由于被处理的对象无法扩展属性,所以 Object.isExtensible(obj) 也是 false。

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

使用 Object.defineProperty 更改 value 会直接报错。

obj.a = 10 也失败。

使用 Object.isFrozen(),判断是否被 freeze 了。

能否更改深层对象的属性
Object.seal 是可以更改第一层属性对应的值。
Object.freeze 是不能更改第一层属性对应的值,但可以更改更深层次的值!!!
obj1.a.name = 'yuny' 直接把 name 变成了 yuny。

广告时间
欢迎关注,每日进步!!!
