深入理解 Object.keys() 顺序问题

深入理解 Object.keys()

我们先来看看在 MDN[6] 上关于 Object.keys() 的描述:

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

emmm... 并没有直接告诉我们输出顺序是什么,不过我们可以看看上面的 Polyfill[7] 是怎么写的:

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 = [];//1.创建一个空的列表用于存放 keys

      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;
    }
  })()
};
  1. 创建一个空的列表用于存放 keys
  2. 将所有合法的数组索引按升序的顺序存入
  3. 将所有字符串类型索引按属性创建时间以升序的顺序存入
  4. 将所有 Symbol 类型索引按属性创建时间以升序的顺序存入
  5. 返回 keys

这里顺便也纠正一个普遍的误区:有些回答说将所有属性为数字类型的 key 从小到大排序,其实不然,还必须要符合 「合法的数组索引」 ,也即只有正整数才行,负数或者浮点数,一律当做字符串处理。

PS:严格来说对象属性没有数字类型的,无论是数字还是字符串,都会被当做字符串来处理。

    let o = {
        2: "b",
        3: "c",
        1: "a"
        }

    console.log(Object.keys(o))
    Object.keys(o).forEach((value, index, array) => {
        console.log(value);
    })




//打印
(3) ["1", "2", "3"]

1
2
3

看下这个例子:

const testObj = {}

testObj[-1] = ''
testObj[1] = ''
testObj[1.1] = ''
testObj['2'] = ''
testObj['c'] = ''
testObj['b'] = ''
testObj['a'] = ''
testObj[Symbol(1)] = ''
testObj[Symbol('a')] = ''
testObj[Symbol('b')] = ''
testObj['d'] = ''

console.log(Object.keys(testObj))

结果:

['1', '2', '-1', '1.1', 'c', 'b', 'a', 'd']

我们如果想实现对象属性是数字,并且还要按照存入的顺序,返回
将数字转换为浮点型即可

你可能感兴趣的:(深入理解 Object.keys() 顺序问题)