前言:
获取对象的可枚举属性有很多的方法:例如for in循环,Object.keys(),Object.getOwnPropertyNames(),Object.getOwnPropertySymbols()以及Object.assign(),他们在属性枚举方面有很大的区别,你了解多少呢?
枚举顺序不定:
for-in循环和Object.keys():
这两种方式枚举属性的顺序是不确定的,取决于javaScript引擎,可能因浏览器而异。
区别:
- for-in循环会遍历对象所有的可枚举属性(不包括Symbol),包括对象自身的和对象原型上的。
- Object.keys()仅会遍历对象自身的所有可枚举属性(不包括Symbol),而不会遍历对象原型。
const obj = { a: 1, b: 2 };
Object.prototype.c = 3; // 添加到原型链上
for (const key in obj) {
console.log(key, obj[key]);
}
// 输出:
// a 1
// b 2
// c 3 (包括原型链上的属性)
// 如果只想遍历对象自身的属性:
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key]);
}
}
// 输出:
// a 1
// b 2
const obj = { a: 1, b: 2 };
Object.prototype.c = 3; // 添加到原型链上
const keys = Object.keys(obj);
console.log(keys);
// 输出: ['a', 'b'] (只包含对象自身的属性)
keys.forEach(key => {
console.log(key, obj[key]);
});
// 输出:
// a 1
// b 2
枚举顺序确定:
Object.getOwnPropertyNames(),Object.getOwnPropertySymbols()以及Object.assign():
三者的遍历顺序是确定的,首先升序遍历数字类型的属性,然后按照插入顺序遍历字符串和符号类型的属性。举个例子,以Object.getOwnPropertyNames()为例:
let key='key'
let obj= {
1:'haha',
[Symbol('m')]:'Symbol_m',
3:'jjjj',
"second":'dier',
"first":'diyi',
[key]:'key_value'
}
obj.__proto__.name='objName'
console.log(Object.getOwnPropertyNames(obj))
注意,返回的数组中,所有元素都变成字符串格式。
区别:
Object.getOwnPropertyNames(obj)
:
返回对象自身的所有属性(包括不可枚举属性,但不包括 Symbol
属性)的键名数组。
const obj = { a: 1, b: 2 };
Object.defineProperty(obj, 'c', { value: 3, enumerable: false });
console.log(Object.getOwnPropertyNames(obj));
// 输出: ['a', 'b', 'c'] (包括不可枚举属性)
Object.getOwnPropertySymbols(obj):
返回一个由指定对象自身的所有 Symbol
类型的属性键名组成的数组。
const obj = {
a: 1,
b: 2
};
const sym1 = Symbol('c');
const sym2 = Symbol('d');
obj[sym1] = 3;
obj[sym2] = 4;
console.log(Object.getOwnPropertySymbols(obj));
// 输出: [Symbol(c), Symbol(d)]
Object.assign(target, ...sources):
将一个或多个源对象的所有可枚举的自身属性复制到目标对象中,并返回目标对象。
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 } (目标对象被修改)