-
事件背景
- 最近在写常量对象枚举时,发现循环Object.keys得出了顺序,并不是创建时的顺序
- 于是查了查,果然有坑,
- MDN表述:
Object.keys 返回一个所有元素为字符串的数组,其元素来自于从给定的object上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致【真要命,具体啥顺序,没说】- MDN polifill【可以看出Object.keys是和for in 是一致的,这个就和红宝书上说的对上了】
if (!Object.keys) { Object.keys = (function () { var hasOwnProperty = Object.prototype.hasOwnProperty, hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ], dontEnumsLength = dontEnums.length; return function (obj) { if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object'); var result = []; for (var prop in obj) { if (hasOwnProperty.call(obj, prop)) result.push(prop); } if (hasDontEnumBug) { for (var i=0; i < dontEnumsLength; i++) { if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]); } } return result; } })() }; - 红宝书表述:
for-in循环、Object.keys()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()以及Object.assign()在属性枚举顺序方面有很大区别。for-in循环和Object.keys()的枚举顺序是不确定的,取决于JavaScript引擎,可能因浏览器而异。Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()和Object.assign()的枚举顺序是确定性的。先以升序枚举数值键,然后以插入顺序枚举字符串和符号键。在对象字面量中定义的键以它们逗号分隔的顺序插入。 - 现在的情况是:Object.keys()也会先序列化升序
- MDN表述:
-
Object.keys(xxx)的返回值并不一定是对象内的创建顺序
- 示例Ex:
const a = { 1:[1], 3:[3], 2:[2] } console.log(Object.keys(a))//[1,2,3] // 出乎意料的,输出的结果并不是创建顺序[1,3,2]而是序列化之后的[1,2,3] -
Object.values(xxx)的返回值同理也是,并不一定是对象内的创建顺序
- Object.values(xxx)的顺序完全是Object.keys序列化键之后对应的值得序列化
- 示例Ex:
const a = { 1:[1], 3:[3], 2:[2] } console.log(Object.values(a))//[[1],[2],[3]] // 出乎意料的,输出的结果并不是创建顺序[[1],[3],[2]]而是序列化之后的[[1],[2],[3]] -
总结:尽量不要让数字或者时间戳数字等作为对象的键,尤其是在列对象枚举时,这简直是个致命的伤,既会影响Object.keys的值也会影响Object.values的值
-
彩蛋补充:Object.keys和Object.values只能处理可枚举的对象,对于Symbol类枚举键,是不可获取的
- 示例Ex:
const a = Symbol() const p = {x:1, y:2, [a]:"666"} Object.keys(p); //["x","y"] -
参考文献
- MDN developer.mozilla.org/zh-CN/docs/… 【推荐】
- 红宝书【属性枚举顺序】【 www.dedao.cn/ebook/reade… 】 【推荐】
- mp.weixin.qq.com/s/foXbAj3OD…
- juejin.cn/post/704104…