JavaScript 对象遍历方法及其遍历顺序的总结
JavaScript 对象遍历方法及其遍历顺序的总结
0.从规范中定义的内部 ownPropertyKeys 方法说起
这个方法定义了一个对象的遍历顺序:
- 先将 整数属性 按 升序 排列。
- 再将 字符串属性 按 定义顺序 排列。
- 最后将 Symbol 符号属性 按 定义顺序 排列。
其中,整数属性的定义为:
- +0 <= parseFloat(key) < 2^32 - 1 (最大安全整数)
- 不作任何修改便可以与一个整数值相互转换
alert( String(Math.trunc(Number("49"))) ); // "49",相同,整数属性
alert( String(Math.trunc(Number("+49"))) ); // "49",不同于 "+49" ⇒ 不是整数属性
alert( String(Math.trunc(Number("1.2"))) ); // "1",不同于 "1.2" ⇒ 不是整数属性
这个遍历顺序广泛地应用在了各种遍历方式之中。
1.使用 ownPropertyKeys 遍历顺序的方法
Object.getOwnPropertyNames()
- 获取所有实例字符串属性的字符串数组。
- 忽略 Symbol 属性。
- 无论是否可枚举都会被获取。
Object.getOwnPropertySymbols()
- 获取所有实例符号(Symbol)属性的数组。
- 返回结果只有符号属性。
- 无论是否可枚举都会被获取。
Object.assign()
- 使用方法: Object.assign(目标对象,一个或多个源对象)
- 作用:将源对象上的属性复制到目标对象上,并将目标对象的引用返回。
- 被复制的对象:实例上所有的可枚举属性。
Object.propertyIsEnumerable() === true &&
Object.hasOwnProperty() === true
Reflect.ownKeys()
- 获取所有 实例属性 的数组。
- 返回结果有 字符串属性 和 符号属性。
- 无论是否可枚举都会被获取。
- 相当于
Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
示例:
定义一个 obj 对象:
let s = Symbol("1");
let s2 = Symbol("2");
let obj = {
'1e':"1",
'0':"2",
'+5':"3",
[s2]:"3.5",
'2':"4",
'2haha':"5",
[s]:"6",
}
使用下列方式遍历:
console.log(Object.getOwnPropertyNames(obj)) //["0","2","1e","+5","2haha"]
console.log(Object.getOwnPropertySymbols(obj)) //[Symbol(2),Symbol(1)]
console.log(Reflect.ownKeys(obj)); //["0","2","1e","+5","2haha",Symbol(2),Symbol(1)]
console.log(Object.assign({},obj));
/*
{
"0":"2",
"2":"4",
"1e":"1",
"+5":"3",
"2haha":"5"
}
*/
2.For…of
for…of 可以遍历可迭代对象,即实现了 Symbol.iterator 方法的对象。
2.1 遍历的顺序
遍历的顺序为 调用 Symbol.iterator 工厂方法返回的迭代器中, next() 方法的返回值顺序。
3.For…in
3.1 遍历的范围
▲ for…in 方法可以遍历对象 实例上 的及 原型链上 的 所有 可枚举属性([[Enumerable]]: true)。
▲ 忽略 Symbol 属性。
▲ 对 null / undefined 遍历将不会执行循环体。
3.2 遍历的顺序
for…in 方法遍历的顺序在不同浏览器 JavaScript 引擎中表现不一。
3.2.1 在 Chrome / Opera 中
遵循上述的 ownPropertyKeys 方法 的顺序排列。
【示例】
对上述定义的 obj 遍历:
for(let k in obj){
console.log(k);
}
3.2.2 在其他浏览器中
按照属性定义的顺序排列。
4.Object.keys()
4.1 遍历的范围
▲ Object.keys() 方法可以遍历对象 实例上 的所有 可枚举属性。
▲ 忽略 Symbol 属性。
▲ 参数为 null / undefined 时会抛出错误。
Uncaught TypeError: Cannot convert undefined or null to object
4.2 遍历的顺序
Object.keys() 方法遍历的顺序在不同浏览器 JavaScript 引擎中表现不一。
具体表现与 for…in 一致。
【示例】
对上述定义的 obj 遍历:
console.log(Object.keys(obj)); //["0","2","1e","+5","2haha"]
参考文章
▲ Object.keys(…)对象属性的顺序?
▲ 一起学规范系列 —— Object.keys() 的顺序是如何定义的?
▲ 【JS】for in和for of的前世今生,从Symbol和Iterator讲起