引言
JavaScript 对象是前端开发中最基本的概念之一,几乎每个开发者每天都在与对象打交道。你可能已经熟悉了对象的创建、属性访问等基础操作,但你知道 JavaScript 原生对象(Object
)实际上拥有多达29个内置方法吗?这些方法涵盖了对象属性的管理、对象自身的描述和操作等多个方面,为开发者提供了强大的工具集。今天,我们就来全面梳理一下这些方法,看看你到底掌握了多少。
1. 属性相关方法
1.1 Object.keys()
返回对象自身的可枚举属性名组成的数组。
const obj = { a: 1, b: 2, c: 3 };
console.log(Object.keys(obj)); // ["a", "b", "c"]
1.2 Object.values()
返回对象自身的可枚举属性值组成的数组。
console.log(Object.values(obj)); // [1, 2, 3]
1.3 Object.entries()
返回对象自身的可枚举属性键值对数组。
console.log(Object.entries(obj)); // [["a", 1], ["b", 2], ["c", 3]]
1.4 Object.getOwnPropertyNames()
返回一个数组,包含对象自身的所有属性名(包括不可枚举属性,但不包括Symbol属性)。
const obj = { a: 1 };
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
console.log(Object.getOwnPropertyNames(obj)); // ["a", "b"]
1.5 Object.getOwnPropertySymbols()
返回一个数组,包含对象自身的所有 Symbol 属性。
const sym = Symbol('foo');
const obj = { [sym]: 1 };
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(foo)]
1.6 Object.getOwnPropertyDescriptor()
返回指定对象属性的描述符。
const obj = { a: 1 };
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// { value: 1, writable: true, enumerable: true, configurable: true }
1.7 Object.defineProperty()
直接在对象上定义新属性或修改现有属性,并返回对象。
Object.defineProperty(obj, 'b', {value: 2,writable: true,enumerable: false,configurable: true,
});
console.log(obj.b); // 2
1.8 Object.defineProperties()
直接在对象上定义一个或多个新属性或修改现有属性,并返回对象。
Object.defineProperties(obj, {c: {value: 3,writable: true,enumerable: true,configurable: true,},d: {value: 4,writable: false,enumerable: false,configurable: true,},
});
1.9 Object.hasOwnProperty()
判断对象是否包含特定属性(非继承属性)。
console.log(obj.hasOwnProperty('a')); // true
1.10 Object.propertyIsEnumerable()
判断对象的特定属性是否可枚举。
console.log(obj.propertyIsEnumerable('b')); // false
2. 原型链与继承相关方法
2.1 Object.create()
使用指定的原型对象及其属性创建一个新对象。
const proto = { greet() { return 'Hello'; } };
const obj = Object.create(proto);
console.log(obj.greet()); // "Hello"
2.2 Object.getPrototypeOf()
返回指定对象的原型(内部 [[Prototype]] 属性的值)。
console.log(Object.getPrototypeOf(obj) === proto); // true
2.3 Object.setPrototypeOf()
设置对象的原型(内部 [[Prototype]] 属性的值)。
const newProto = { greet() { return 'Hi'; } };
Object.setPrototypeOf(obj, newProto);
console.log(obj.greet()); // "Hi"
2.4 Object.isPrototypeOf()
判断一个对象是否存在于另一个对象的原型链上。
console.log(proto.isPrototypeOf(obj)); // false
console.log(newProto.isPrototypeOf(obj)); // true
3. 对象比较与判断方法
3.1 Object.is()
判断两个值是否为同一个值。
console.log(Object.is('foo', 'foo')); // true
console.log(Object.is({}, {})); // false
console.log(Object.is(NaN, NaN)); // true
3.2 Object.isExtensible()
判断对象是否可扩展。
console.log(Object.isExtensible(obj)); // true
3.3 Object.isFrozen()
判断对象是否被冻结。
console.log(Object.isFrozen(obj)); // false
3.4 Object.isSealed()
判断对象是否被密封。
console.log(Object.isSealed(obj)); // false
3.5 Object.freeze()
冻结对象,使其不可修改。
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true
3.6 Object.seal()
密封对象,使其不可删除属性,但可修改现有属性。
Object.seal(obj);
console.log(Object.isSealed(obj)); // true
3.7 Object.preventExtensions()
阻止对象扩展,使其不能添加新属性。
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj)); // false
4. 其他常用方法
4.1 Object.assign()
将一个或多个源对象的可枚举属性复制到目标对象,并返回目标对象。
const target = { a: 1 };
const source = { b: 2, c: 3 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2, c: 3 }
4.2 Object.fromEntries()
将一个键值对列表(二维数组)转换为对象。
const entries = [['a', 1], ['b', 2]];
const obj = Object.fromEntries(entries);
console.log(obj); // { a: 1, b: 2 }
4.3 Object.toString()
返回对象的字符串表示。
console.log(obj.toString()); // "[object Object]"
5. 新增的ES6+方法
5.1 Object.getOwnPropertyDescriptors()
返回一个对象所有自身属性的描述符。
const obj = { a: 1 };
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// { a: { value: 1, writable: true, enumerable: true, configurable: true } }
5.2 Object.entries()
和 Object.values()
的新用途
这两个方法不仅仅可以用来遍历对象的键和值,还可以通过搭配 Object.fromEntries()
来实现对象的深拷贝。
const original = { a: 1, b: { c: 2 } };
const copy = Object.fromEntries(Object.entries(original));
console.log(copy); // { a: 1, b: { c: 2 } }
总结
JavaScript 的对象操作方法为我们提供了丰富的功能,不仅简化了日常开发中的诸多操作,还为我们提供了更高效的代码组织方式。在日常开发中,掌握这些方法的正确用法,将大大提升我们处理对象相关操作的效率与代码质量。你掌握了多少呢?不妨动手试试这些方法,深入理解每一个方法背后的逻辑与用途吧!