JavaScript 遍历对象属性的方法

前言

JavaScript 是一门面向对象的编程语言,它内置了一些可以遍历对象属性的方法,如 for...in, Object.keys(), Object.getOwnPropertyNames(), Reflect.ownKeys() 等。但这几种方法间存在一些区别,本文就来将它们对比一下。

for…in

for...in 语句是一种精确的迭代语句,可以用来枚举一个对象的所有 可枚举属性,包括对象本身的属性以及从原型链上继承的属性。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let obj = {
a: 1,
b: 2,
c: 3
}
//增加一个不可枚举的属性
Object.defineProperty(obj, 'd', {
value: 4,
enumerable: false
});
//在原型链中添加一个可枚举属性
Object.defineProperty(Object.prototype, 'e', {
value: 5,
enumerable: true
});
for (let key in obj) {
console.log(key); // -> a, b, c, e
}

需要注意的是,由于 ECMAScript 对象的属性没有顺序,通过 for...in 循环输出的属性名的 顺序是不可预测的。也就是说,对象的所有属性都会被返回一次,但返回的先后顺序可能因浏览器而异。

Object.keys()

Object.keys() 方法会返回一个由目标对象的 自身可枚举属性 组成的数组。它只会遍历对象自身的可枚举属性,而不会遍历到从原型链中继承的属性。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let obj = {
a: 1,
b: 2,
c: 3
}
//增加一个不可枚举的属性
Object.defineProperty(obj, 'd', {
value: 4,
enumerable: false
});
//在原型链中添加一个可枚举属性
Object.defineProperty(Object.prototype, 'e', {
value: 5,
enumerable: true
});
console.log(Object.keys(obj)); // -> ["a", "b", "c"]

通过 Object.keys() 返回的数组中,属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致。

Object.getOwnPropertyNames()

Object.getOwnPropertyNames() 方法会返回一个由目标对象的所有自身属性组成的数组,包括自身的不可枚举属性,但它不会遍历到原型链中继承的属性。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let obj = {
a: 1,
b: 2,
c: 3
}
//增加一个不可枚举的属性
Object.defineProperty(obj, 'd', {
value: 4,
enumerable: false
});
//在原型链中添加一个可枚举属性
Object.defineProperty(Object.prototype, 'e', {
value: 5,
enumerable: true
});
console.log(Object.getOwnPropertyNames(obj)); // -> ["a", "b", "c", "d"]

通过 Object.getOwnPropertyNames() 返回的数组中,可枚举属性的排列顺序也与使用 for...in 循环遍历该对象时返回的顺序一致,不可枚举属性的顺序未定义。

Reflect.ownKeys()

Relect 对象是 ES6 为了更好操作对象而提供的新 API,本文主要讨论它的一个静态方法 Reflect.ownKeys()

Reflect.ownKeys() 方法会返回一个由目标对象 所有自身属性 组成的数组,与 Object.getOwnPropertyNames() 相似,但前者返回的数组里还会包括目标对象自身的所有 symbol 属性键,它的返回值等同于
Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let obj = {
a: 1,
b: 2,
c: 3
}
//增加一个不可枚举的属性
Object.defineProperty(obj, 'd', {
value: 4,
enumerable: false
});
//在原型链中添加一个可枚举属性
Object.defineProperty(Object.prototype, 'e', {
value: 5,
enumerable: true
});
console.log(Reflect.ownKeys(obj)); // -> ["a", "b", "c", "d"]
------ 本文结束 ------
坚持原创技术分享,您的支持将鼓励我继续创作!