JavaScript对象(Object)研究_05_is、isExtensible、isFrozen、isSealed、keys、preventExtensions、seal
在JavaScript中,Object
构造函数提供了一系列静态方法,用于操作和管理对象的属性和行为。本篇博客将深入探讨Object
的几个重要静态方法:is
、isExtensible
、isFrozen
、isSealed
、keys
、preventExtensions
、seal
。
一、Object.is()
1. 基础介绍
Object.is()
方法判断两个值是否是同一个值。它类似于严格比较运算符(===
),但在处理NaN
和+0
、-0
时有所不同。
2. 语法
Object.is(value1, value2)
- value1:第一个要比较的值。
- value2:第二个要比较的值。
3. 示例代码
示例1:一般比较
console.log(Object.is(25, 25)); // 输出: true
console.log(Object.is('foo', 'foo')); // 输出: true
console.log(Object.is({}, {})); // 输出: false(不同的对象)
示例2:处理NaN
console.log(Object.is(NaN, NaN)); // 输出: true
console.log(NaN === NaN); // 输出: false
示例3:处理+0
和-0
console.log(Object.is(+0, -0)); // 输出: false
console.log(+0 === -0); // 输出: true
4. 返回值描述
Object.is()
方法返回一个布尔值,表示两个值是否为同一个值。
5. 扩展知识点
-
区别于
===
:Object.is(NaN, NaN)
返回true
,而NaN === NaN
返回false
。Object.is(+0, -0)
返回false
,而+0 === -0
返回true
。
-
使用场景:
当需要精确判断两个值是否相同,尤其是在处理
NaN
或+0
、-0
时,可以使用Object.is()
。
6. 注意事项
Object.is()
不能替代===
或==
,它只是提供了更精确的比较方式。- 在绝大多数情况下,
Object.is()
与===
的行为一致。
二、Object.isExtensible()
1. 基础介绍
Object.isExtensible()
方法判断一个对象是否是可扩展的(即是否可以向对象添加新的属性)。
2. 语法
Object.isExtensible(obj)
- obj:要检测的对象。
3. 示例代码
示例1:默认情况下,对象是可扩展的
const obj = {};
console.log(Object.isExtensible(obj)); // 输出: true
示例2:使用Object.preventExtensions()
const obj = {};
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj)); // 输出: false
obj.newProp = 'value'; // 无效操作,不能添加新属性
console.log(obj.newProp); // 输出: undefined
示例3:密封和冻结对象
const sealedObj = Object.seal({});
console.log(Object.isExtensible(sealedObj)); // 输出: false
const frozenObj = Object.freeze({});
console.log(Object.isExtensible(frozenObj)); // 输出: false
4. 返回值描述
Object.isExtensible()
方法返回一个布尔值,表示对象是否可扩展。
5. 扩展知识点
-
不可扩展对象的特性:
- 不能添加新属性。
- 现有属性的可配置性和可写性不受影响。
-
如何使对象不可扩展:
- 使用
Object.preventExtensions()
。 - 使用
Object.seal()
或Object.freeze()
(它们也会使对象不可扩展)。
- 使用
6. 注意事项
-
只能对对象类型使用,非对象类型会被强制转换为对象,然后返回
false
。console.log(Object.isExtensible(42)); // 输出: false
-
在严格模式下,向不可扩展对象添加属性会抛出
TypeError
错误。
三、Object.isFrozen()
1. 基础介绍
Object.isFrozen()
方法判断一个对象是否被冻结。冻结的对象不能添加新属性,不能删除或修改已有属性,属性的可配置性、可写性都被设置为false
。
2. 语法
Object.isFrozen(obj)
- obj:要检测的对象。
3. 示例代码
示例1:默认情况下,对象不是冻结的
const obj = {};
console.log(Object.isFrozen(obj)); // 输出: false
示例2:使用Object.freeze()
const obj = { a: 1 };
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // 输出: true
obj.a = 2; // 无效操作,不能修改属性
console.log(obj.a); // 输出: 1
示例3:嵌套对象的冻结
const obj = { inner: { b: 2 } };
Object.freeze(obj);
console.log(Object.isFrozen(obj.inner)); // 输出: false(内部对象未被冻结)
4. 返回值描述
Object.isFrozen()
方法返回一个布尔值,表示对象是否被冻结。
5. 扩展知识点
-
浅冻结:
Object.freeze()
是浅冻结,只冻结对象的第一层属性,内部嵌套的对象需要手动冻结。function deepFreeze(obj) { const propNames = Object.getOwnPropertyNames(obj); for (const name of propNames) { const value = obj[name]; if (typeof value === 'object' && value !== null) { deepFreeze(value); } } return Object.freeze(obj); } deepFreeze(obj);
6. 注意事项
- 一个对象如果不可扩展、所有属性不可写、不可配置,则认为是冻结的。
- 数组冻结后,无法修改其元素或长度。
四、Object.isSealed()
1. 基础介绍
Object.isSealed()
方法判断一个对象是否被密封。密封的对象不能添加新属性,不能删除已有属性,但可以修改属性的值。
2. 语法
Object.isSealed(obj)
- obj:要检测的对象。
3. 示例代码
示例1:默认情况下,对象不是密封的
const obj = {};
console.log(Object.isSealed(obj)); // 输出: false
示例2:使用Object.seal()
const obj = { a: 1 };
Object.seal(obj);
console.log(Object.isSealed(obj)); // 输出: true
obj.a = 2; // 可以修改属性值
console.log(obj.a); // 输出: 2
delete obj.a; // 无效操作,不能删除属性
console.log(obj.a); // 输出: 2
obj.b = 3; // 无效操作,不能添加新属性
console.log(obj.b); // 输出: undefined
4. 返回值描述
Object.isSealed()
方法返回一个布尔值,表示对象是否被密封。
5. 扩展知识点
-
密封对象的特性:
- 不能添加新属性或删除已有属性。
- 现有属性的可配置性被设置为
false
。 - 属性的可写性不受影响,可以修改属性的值(前提是属性的
writable
为true
)。
-
如何使对象密封:
- 使用
Object.seal()
方法。
- 使用
6. 注意事项
- 一个对象如果不可扩展、所有属性不可配置,则认为是密封的。
- 数组密封后,无法改变其长度,也不能添加或删除元素,但可以修改现有元素的值。
五、Object.keys()
1. 基础介绍
Object.keys()
方法返回一个由给定对象自身可枚举属性组成的数组,属性名以字符串形式表示。
2. 语法
Object.keys(obj)
- obj:要返回其自身可枚举属性的对象。
3. 示例代码
示例1:获取对象的可枚举属性
const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
console.log(keys); // 输出: ['a', 'b', 'c']
示例2:不可枚举属性
const obj = { a: 1 };
Object.defineProperty(obj, 'b', {
value: 2,
enumerable: false
});
const keys = Object.keys(obj);
console.log(keys); // 输出: ['a']
示例3:数组的键
const arr = ['x', 'y', 'z'];
const keys = Object.keys(arr);
console.log(keys); // 输出: ['0', '1', '2']
4. 返回值描述
Object.keys()
方法返回一个数组,包含了对象自身的可枚举属性名,以字符串形式表示。
5. 扩展知识点
-
与
for...in
循环的区别:for...in
循环会遍历对象自身的可枚举属性和继承自原型链的可枚举属性。Object.keys()
只返回对象自身的可枚举属性。
-
获取所有属性(包括不可枚举):
- 使用
Object.getOwnPropertyNames(obj)
可以获取对象自身的所有属性,包括不可枚举属性。
- 使用
6. 注意事项
-
属性名的顺序:
- 属性名的顺序是按照整数索引属性升序排列,然后是字符串属性按照创建时的顺序。
-
不包括Symbol类型的属性。
六、Object.preventExtensions()
1. 基础介绍
Object.preventExtensions()
方法让一个对象变得不可扩展,也就是不能再添加新的属性。现有属性的可配置性和可写性不受影响。
2. 语法
Object.preventExtensions(obj)
- obj:要变为不可扩展的对象。
3. 示例代码
示例1:使对象不可扩展
const obj = { a: 1 };
Object.preventExtensions(obj);
obj.b = 2; // 无效操作,不能添加新属性
console.log(obj.b); // 输出: undefined
console.log(Object.isExtensible(obj)); // 输出: false
示例2:修改现有属性
obj.a = 3; // 可以修改现有属性的值
console.log(obj.a); // 输出: 3
delete obj.a; // 可以删除现有属性
console.log(obj.a); // 输出: undefined
4. 返回值描述
Object.preventExtensions()
方法返回被传递的对象(即不可扩展的对象)。
5. 扩展知识点
-
如何检测对象是否可扩展:
- 使用
Object.isExtensible(obj)
方法。
- 使用
-
不可扩展对象的特性:
- 不能添加新属性。
- 可以删除已有属性。
- 现有属性的可写性和可配置性不受影响。
6. 注意事项
- 只能对对象类型使用,非对象类型会被强制转换为对象,然后返回该对象。
七、Object.seal()
1. 基础介绍
Object.seal()
方法封闭一个对象,防止添加或删除属性。现有属性的值可以修改,但属性的可配置性会被设置为false
。
2. 语法
Object.seal(obj)
- obj:要封闭的对象。
3. 示例代码
示例1:封闭对象
const obj = { a: 1 };
Object.seal(obj);
obj.b = 2; // 无效操作,不能添加新属性
console.log(obj.b); // 输出: undefined
delete obj.a; // 无效操作,不能删除属性
console.log(obj.a); // 输出: 1
obj.a = 3; // 可以修改属性的值
console.log(obj.a); // 输出: 3
console.log(Object.isSealed(obj)); // 输出: true
4. 返回值描述
Object.seal()
方法返回被传递的对象(即被封闭的对象)。
5. 扩展知识点
-
密封对象的特性:
- 不能添加新属性或删除已有属性。
- 所有属性的可配置性被设置为
false
。 - 可以修改属性的值(如果属性的
writable
为true
)。
-
如何检测对象是否被密封:
- 使用
Object.isSealed(obj)
方法。
- 使用
6. 注意事项
- 数组被封闭后,不能改变其长度,也不能添加或删除元素,但可以修改现有元素的值。
注意事项总结
-
Object.is()
:用于比较两个值是否是同一个值,特别处理了NaN
和+0
、-0
的比较。返回布尔值。 -
Object.isExtensible()
:判断对象是否可扩展(能否添加新属性)。返回布尔值。 -
Object.isFrozen()
:判断对象是否被冻结(不能添加、删除、修改属性)。返回布尔值。 -
Object.isSealed()
:判断对象是否被密封(不能添加或删除属性,但可修改属性值)。返回布尔值。 -
Object.keys()
:返回对象自身的可枚举属性名数组。返回字符串数组。 -
Object.preventExtensions()
:使对象不可扩展,不能添加新属性。返回被修改的对象。 -
Object.seal()
:封闭对象,不能添加或删除属性,属性的可配置性被设置为false
。返回被修改的对象。
深入理解这些方法,有助于我们更好地控制对象的属性和状态,提高代码的健壮性和可维护性。在实际开发中,善于利用这些方法,可以让我们的代码更加严谨和可靠。
参考资料: