一、Object方法概述
在JavaScript中,Object
是所有对象的基类,提供了许多强大的静态方法来操作和检查对象。这些方法涵盖了从对象创建、属性操作到原型管理等各个方面,是每位JavaScript开发者必须掌握的核心工具。
二、对象创建与属性定义
1. Object.create()
创建一个新对象,使用现有对象作为新对象的原型。除了一点抛弃原有的对象造成的轻微性能损失,它真是原型继承的万金油了。具体细节可以看看我的这篇文章JavaScript原型链的黑魔法:为什么90%的开发者用错了Object.create?
javascript
const parent = { name: 'Parent' };
const child = Object.create(parent, {
age: { value: 10, writable: true }
});
console.log(child.name); // "Parent" (继承)
2. Object.defineProperty()
直接在一个对象上定义或修改属性。底层API,用于精确控制对象的属性行为。
javascript
const obj = {};
Object.defineProperty(obj, 'readOnlyProp', {
value: 42,
writable: false
});
obj.readOnlyProp = 100; // 静默失败或TypeError(严格模式)
3. Object.defineProperties()
同时定义或修改多个属性。
javascript
const obj = {};
Object.defineProperties(obj, {
prop1: { value: true, writable: true },
prop2: { value: 'Hello', enumerable: false }
});
三、对象属性操作
4. Object.getOwnPropertyDescriptor()
获取对象属性的描述符。
javascript
const desc = Object.getOwnPropertyDescriptor(obj, 'prop1');
console.log(desc.writable); // true
5. Object.getOwnPropertyNames()
返回对象自身所有属性名(包括不可枚举属性)。
javascript
const arr = ['a', 'b'];
console.log(Object.getOwnPropertyNames(arr));
// ["0", "1", "length"]
6. Object.keys()
返回对象自身可枚举属性名数组。(length不可枚举)
javascript
const obj = { a: 1, b: 2 };
console.log(Object.keys(obj)); // ["a", "b"]
四、原型链操作
7. Object.getPrototypeOf()
获取对象的原型。
javascript
const proto = Object.getPrototypeOf(child);
console.log(proto === parent); // true
8. Object.setPrototypeOf()
设置对象的原型(慎用,性能敏感)。
javascript
const newProto = { newProp: 'value' };
Object.setPrototypeOf(obj, newProto);
五、对象冻结与密封
9. Object.freeze()
冻结对象,使其不可修改。最高级别不可变性
,禁止对象本身及任意直接属性的修改(但不影响它引用的其他对象)
javascript
const frozen = Object.freeze({ prop: 'value' });
frozen.prop = 'new'; // 静默失败或TypeError
ps:"深度冻结":在这个对象调用Object.freeze(),然后遍历它引用的所有对象并在这些对象上调用Object.freeze()。一定要小心无意冻结其他共享对象
!
10. Object.seal()
密封对象,阻止添加、删除和配置任何属性但允许修改现有属性的值。
javascript
const sealed = Object.seal({ prop: 'value' });
sealed.newProp = 'new'; // 静默失败
sealed.prop = 'updated'; // 允许修改
六、对象合并与复制
11. Object.assign()
合并多个对象的可枚举属性(浅拷贝)。有同名属性后面的会覆盖
javascript
const target = { a: 1 };
const source = { b: 2 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2 }
12. Object.fromEntries()
将键值对列表转换为对象(ES2019)。
javascript
const entries = [['a', 1], ['b', 2]];
const obj = Object.fromEntries(entries);
console.log(obj); // { a: 1, b: 2 }
七、对象比较与遍历
13. Object.is()
增强型严格相等比较。和"==="基本一致,只有两点不同:
javascript
NaN === NaN;//false
+0 === -0; //true
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(0, -0)); // false
14. Object.values()
返回对象可枚举属性值的数组。
javascript
const obj = { a: 1, b: 2 };
console.log(Object.values(obj)); // [1, 2]
15. Object.entries()
返回对象可枚举键值对数组。
javascript
console.log(Object.entries(obj)); // [["a", 1], ["b", 2]]
八、高级应用与最佳实践
1. 深拷贝实现
结合JSON方法和递归:
javascript
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj);
const clone = Object.create(Object.getPrototypeOf(obj));
for (const key of Object.getOwnPropertyNames(obj)) {
clone[key] = deepClone(obj[key]);
}
return clone;
}
2. 属性枚举控制
创建不可枚举但可访问的属性:
javascript
const secretObj = {};
Object.defineProperty(secretObj, 'secret', {
value: 'confidential',
enumerable: false
});
console.log('secret' in secretObj); // true
console.log(Object.keys(secretObj)); // []
3. 不可变数据模式
结合冻结和密封:
javascript
const immutable = Object.freeze({
config: Object.seal({
apiUrl: 'https://api.example.com',
timeout: 3000
})
});
九、方法对比速查表
方法分类 | 方法名 | 典型应用场景 |
---|---|---|
对象创建 | create , defineProperty |
原型继承、属性精细控制 |
属性访问 | keys , values , entries |
对象遍历、转换为数组 |
原型操作 | getPrototypeOf , setPrototypeOf |
继承关系管理 |
对象限制 | freeze , seal |
创建不可变对象 |
属性描述 | getOwnPropertyDescriptor |
高级属性操作 |
对象转换 | fromEntries |
Map/数组转对象 |

十、常见问题解答
Q1: Object.assign是深拷贝吗? A: 不是,Object.assign只进行浅拷贝。对于嵌套对象,会复制引用而非创建新对象。
Q2: 如何判断对象是否被冻结? A: 使用Object.isFrozen(obj)
方法。
Q3: Object.keys和for...in的区别? A: Object.keys
只返回对象自身的可枚举属性,而for...in
会遍历原型链上的可枚举属性。
十一、总结
JavaScript的Object方法提供了强大的对象操作能力:
- 掌握创建和定义方法(create/defineProperty)是对象操作的基础
- 合理使用冻结和密封方法可以增强代码健壮性
- 原型相关方法在继承和类设计中至关重要
- 新的ES6+方法(如fromEntries)让对象转换更便捷
建议开发者根据实际需求选择合适的方法组合,并在性能敏感场景(如setPrototypeOf)特别注意优化问题。