JavaScript对象方法
JavaScript提供了丰富的对象方法,用于创建、操作、遍历和继承对象。这些方法可以帮助我们更高效地处理对象数据。
对象的创建方法
1. Object.create()
Object.create() 方法使用指定的原型对象和属性创建一个新对象。
// 创建一个原型对象
const personPrototype = {
greet: function() {
console.log(`Hello, my name is ${this.name}!`);
}
};
// 使用Object.create()创建新对象
const person = Object.create(personPrototype);
person.name = 'Alice';
person.age = 30;
person.greet(); // Hello, my name is Alice!
console.log(Object.getPrototypeOf(person) === personPrototype); // true2. Object.assign()
Object.assign() 方法用于将所有可枚举的自有属性从一个或多个源对象复制到目标对象。
// Object.assign()示例
const target = { a: 1, b: 2 };
const source1 = { b: 3, c: 4 };
const source2 = { d: 5 };
const result = Object.assign(target, source1, source2);
console.log(result); // { a: 1, b: 3, c: 4, d: 5 }
console.log(target); // { a: 1, b: 3, c: 4, d: 5 }(目标对象被修改)
// 创建一个新对象,避免修改原对象
const newObj = Object.assign({}, target, { e: 6 });
console.log(newObj); // { a: 1, b: 3, c: 4, d: 5, e: 6 }3. Object.freeze()
Object.freeze() 方法冻结一个对象,使其不能被修改(不能添加、修改或删除属性)。
// Object.freeze()示例
const frozenObject = { a: 1, b: 2 };
Object.freeze(frozenObject);
// 尝试修改冻结对象的属性,不会生效
frozenObject.c = 3;
console.log(frozenObject.c); // undefined
frozenObject.a = 10;
console.log(frozenObject.a); // 1(属性值不变)
// 尝试删除冻结对象的属性,不会生效
delete frozenObject.b;
console.log(frozenObject.b); // 2(属性未被删除)
console.log(Object.isFrozen(frozenObject)); // true4. Object.seal()
Object.seal() 方法密封一个对象,使其不能添加或删除属性,但可以修改现有属性。
// Object.seal()示例
const sealedObject = { a: 1, b: 2 };
Object.seal(sealedObject);
// 尝试添加新属性,不会生效
sealedObject.c = 3;
console.log(sealedObject.c); // undefined
// 可以修改现有属性
sealedObject.a = 10;
console.log(sealedObject.a); // 10
// 尝试删除属性,不会生效
delete sealedObject.b;
console.log(sealedObject.b); // 2
console.log(Object.isSealed(sealedObject)); // true5. Object.preventExtensions()
Object.preventExtensions() 方法防止对象扩展,使其不能添加新属性。
// Object.preventExtensions()示例
const obj = { a: 1, b: 2 };
Object.preventExtensions(obj);
// 尝试添加新属性,不会生效
obj.c = 3;
console.log(obj.c); // undefined
// 可以修改和删除现有属性
obj.a = 10;
delete obj.b;
console.log(obj); // { a: 10 }
console.log(Object.isExtensible(obj)); // false对象的属性操作方法
1. Object.defineProperty()
Object.defineProperty() 方法直接在对象上定义一个新属性,或者修改现有属性,并返回该对象。
// Object.defineProperty()示例
const obj = {};
// 定义一个新属性
Object.defineProperty(obj, 'name', {
value: 'Alice',
writable: true,
enumerable: true,
configurable: true
});
console.log(obj.name); // Alice
// 修改现有属性
Object.defineProperty(obj, 'name', {
writable: false
});
obj.name = 'Bob'; // 尝试修改不可写属性,严格模式下会抛出错误
console.log(obj.name); // Alice(属性值未改变)2. Object.defineProperties()
Object.defineProperties() 方法直接在对象上定义多个新属性,或者修改现有属性,并返回该对象。
// Object.defineProperties()示例
const obj = {};
Object.defineProperties(obj, {
name: {
value: 'Alice',
writable: true
},
age: {
value: 30,
writable: false
},
greet: {
value: function() {
console.log(`Hello, my name is ${this.name}!`);
},
enumerable: false
}
});
console.log(obj.name); // Alice
console.log(obj.age); // 30
obj.greet(); // Hello, my name is Alice!3. Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性的属性描述符。
// Object.getOwnPropertyDescriptor()示例
const obj = {
name: 'Alice',
age: 30
};
const descriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(descriptor);
// 输出:
// {
// value: 'Alice',
// writable: true,
// enumerable: true,
// configurable: true
// }4. Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 方法返回指定对象所有自有属性的属性描述符。
// Object.getOwnPropertyDescriptors()示例
const obj = {
name: 'Alice',
age: 30
};
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// 输出:
// {
// name: {
// value: 'Alice',
// writable: true,
// enumerable: true,
// configurable: true
// },
// age: {
// value: 30,
// writable: true,
// enumerable: true,
// configurable: true
// }
// }5. Object.hasOwnProperty()
Object.hasOwnProperty() 方法判断对象自身是否具有指定的属性(不包括继承的属性)。
// Object.hasOwnProperty()示例
const obj = {
name: 'Alice',
age: 30
};
console.log(obj.hasOwnProperty('name')); // true
console.log(obj.hasOwnProperty('toString')); // false(toString是继承的属性)
// 遍历对象自身的属性
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(`${key}: ${obj[key]}`);
}
}
// 输出:
// name: Alice
// age: 30对象的遍历方法
1. Object.keys()
Object.keys() 方法返回对象自身的可枚举属性的数组。
// Object.keys()示例
const obj = {
name: 'Alice',
age: 30,
occupation: 'Engineer'
};
const keys = Object.keys(obj);
console.log(keys); // ['name', 'age', 'occupation']
keys.forEach(key => {
console.log(`${key}: ${obj[key]}`);
});2. Object.values()
Object.values() 方法返回对象自身的可枚举属性值的数组。
// Object.values()示例
const obj = {
name: 'Alice',
age: 30,
occupation: 'Engineer'
};
const values = Object.values(obj);
console.log(values); // ['Alice', 30, 'Engineer']3. Object.entries()
Object.entries() 方法返回对象自身的可枚举属性键值对的数组。
// Object.entries()示例
const obj = {
name: 'Alice',
age: 30,
occupation: 'Engineer'
};
const entries = Object.entries(obj);
console.log(entries); // [['name', 'Alice'], ['age', 30], ['occupation', 'Engineer']]
// 使用Object.entries()和for...of遍历对象
for (const [key, value] of entries) {
console.log(`${key}: ${value}`);
}4. Object.getOwnPropertyNames()
Object.getOwnPropertyNames() 方法返回对象自身的所有属性(包括不可枚举属性)的数组。
// Object.getOwnPropertyNames()示例
const obj = {
name: 'Alice',
age: 30
};
// 添加一个不可枚举属性
Object.defineProperty(obj, 'id', {
value: 123,
enumerable: false
});
const allKeys = Object.getOwnPropertyNames(obj);
console.log(allKeys); // ['name', 'age', 'id']5. Object.getOwnPropertySymbols()
Object.getOwnPropertySymbols() 方法返回对象自身的所有Symbol属性的数组。
// Object.getOwnPropertySymbols()示例
const sym1 = Symbol('sym1');
const sym2 = Symbol('sym2');
const obj = {
[sym1]: 'value1',
name: 'Alice'
};
obj[sym2] = 'value2';
const symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols); // [Symbol(sym1), Symbol(sym2)]
console.log(obj[symbols[0]]); // value16. Reflect.ownKeys()
Reflect.ownKeys() 方法返回对象自身的所有键,包括字符串键和Symbol键,无论是否可枚举。
// Reflect.ownKeys()示例
const sym = Symbol('sym');
const obj = {
name: 'Alice',
[sym]: 'symbol value'
};
Object.defineProperty(obj, 'id', {
value: 123,
enumerable: false
});
const keys = Reflect.ownKeys(obj);
console.log(keys); // ['name', 'id', Symbol(sym)]对象的继承方法
1. Object.setPrototypeOf()
Object.setPrototypeOf() 方法设置一个对象的原型(即内部 [[Prototype]] 属性)。
// Object.setPrototypeOf()示例
const animal = {
type: 'Unknown',
makeSound: function() {
console.log(`${this.type} makes a sound.`);
}
};
const dog = {
name: 'Buddy'
};
// 设置dog的原型为animal
Object.setPrototypeOf(dog, animal);
dog.type = 'Dog';
dog.makeSound(); // Dog makes a sound.
console.log(Object.getPrototypeOf(dog) === animal); // true2. Object.getPrototypeOf()
Object.getPrototypeOf() 方法返回指定对象的原型(即内部 [[Prototype]] 属性的值)。
// Object.getPrototypeOf()示例
const obj = {};
const proto = Object.getPrototypeOf(obj);
console.log(proto === Object.prototype); // true
const arr = [];
const arrProto = Object.getPrototypeOf(arr);
console.log(arrProto === Array.prototype); // true3. Object.prototype.isPrototypeOf()
isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
// isPrototypeOf()示例
const animal = { type: 'Animal' };
const dog = Object.create(animal);
const buddy = Object.create(dog);
console.log(animal.isPrototypeOf(dog)); // true
console.log(animal.isPrototypeOf(buddy)); // true
console.log(dog.isPrototypeOf(buddy)); // true
console.log(buddy.isPrototypeOf(animal)); // false对象的其他方法
1. Object.is()
Object.is() 方法判断两个值是否为同一个值,比 === 运算符更严格。
// Object.is()示例
console.log(Object.is(1, 1)); // true
console.log(Object.is(1, '1')); // false
console.log(Object.is(NaN, NaN)); // true(=== 运算符会返回false)
console.log(Object.is(+0, -0)); // false(=== 运算符会返回true)
console.log(Object.is({}, {})); // false(引用不同)2. Object.prototype.toString()
toString() 方法返回对象的字符串表示。
// Object.prototype.toString()示例
const obj = {};
console.log(obj.toString()); // [object Object]
const arr = [];
console.log(arr.toString()); // ""
const date = new Date();
console.log(date.toString()); // 例如:Wed Jan 17 2024 10:30:00 GMT+0800 (中国标准时间)
const func = function() {};
console.log(func.toString()); // function() {}
// 使用toString()检测数据类型
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(getType(123)); // Number
console.log(getType('string')); // String
console.log(getType(true)); // Boolean
console.log(getType([])); // Array
console.log(getType({})); // Object
console.log(getType(null)); // Null
console.log(getType(undefined)); // Undefined
console.log(getType(function() {})); // Function3. Object.prototype.valueOf()
valueOf() 方法返回对象的原始值。
// Object.prototype.valueOf()示例
const obj = {
valueOf: function() {
return 42;
}
};
console.log(obj + 1); // 43(obj.valueOf()被调用)
console.log(Number(obj)); // 42(obj.valueOf()被调用)
const date = new Date();
console.log(date.valueOf()); // 返回时间戳,例如:1705482600000对象方法的最佳实践
- 优先使用对象字面量:创建对象时,优先使用对象字面量
{},简洁易读。 - 使用Object.assign()合并对象:合并对象时,使用
Object.assign()方法,避免手动复制属性。 - 使用Object.keys()等方法遍历对象:遍历对象时,优先使用
Object.keys()、Object.values()和Object.entries()方法。 - 使用Object.freeze()保护常量对象:对于不需要修改的对象,使用
Object.freeze()方法冻结,防止意外修改。 - 使用Object.defineProperty()定义属性:需要精确控制属性特性时,使用
Object.defineProperty()方法。 - **避免使用Object.setPrototypeOf()**:设置原型会影响性能,优先使用
Object.create()创建对象。 - 使用Object.is()比较值:需要严格比较值时,使用
Object.is()方法,特别是比较NaN和正负0。 - 使用getType()检测数据类型:使用
Object.prototype.toString.call()检测数据类型,比typeof更准确。