在 console.log 中显示对象属性的原始顺序

IT技术 javascript console.log
2021-02-24 11:18:52

我需要进行一些调试才能查看一个 JavaScript 对象属性的原始顺序,但(至少在 chrome devtools 中)console.log()向我显示了一个按字母顺序排列的对象。

前任:

var obj = {
    z: 1,
    t: 2,
    y: 3,
    a: 4,
    n: 5,
    k: 6
}

console.log(obj) 显示这个:

Object {z: 1, t: 2, y: 3, a: 4, n: 5…}
a:4
k:6
n:5
t:2
y:3
z:1

//expected (needed ) original order
z: 1
t: 2
y: 3
a: 4
n: 5
k: 6
5个回答

console.log确实对属性进行排序,在某些情况下,您可以使用JSON.stringify它来保留顺序,例如

console.log(JSON.stringify(obj, null /*replacer function */, 4 /* space */))

注意:与流行的看法相反,js 对象按照OwnPropertyKeys 规范维护枚举顺序(首先是整数,然后是插入顺序的其他属性)

遗憾的是,您无法使用这种方法折叠键。
2021-04-24 11:18:52

对象确实保留了它们(非数字)键插入的顺序,但它们只能保证使用某些方法按该顺序进行迭代。根据规范Object.keys及其变体,JSON.stringifyfor..in循环都以未指定的顺序迭代。这些方法都调用EnumerateObjectProperties,其中明确指出:

未指定枚举属性的机制和顺序

虽然环境通常以可预测的顺序迭代这些方法,但规范绝不保证这种行为。

但是,Object.getOwnPropertyNames(和Reflect.ownKeys,和Object.getOwnPropertySymbols保证迭代中以特定顺序:升序数字键,接着按插入顺序的其他键,每[[OwnPropertyKeys]]

因此,按插入顺序记录(非数字)属性的规范保证方法将涉及使用上述方法之一,而不是Object.keys或其变体:

var obj = {
  z: 1,
  t: 2,
  y: 3,
  a: 4,
  n: 5,
  k: 6
};

const str = '{\n' +
  Object.getOwnPropertyNames(obj).map(key => `  ${key}: ${obj[key]}`).join('\n')
  + '\n}';
console.log(str);

对于嵌套对象,您将需要一个递归函数:

如果您需要记录一个非常大的对象,以便能够折叠键,另一种选择是将其转换为键值对数组。

let keepKeyOrder = function(obj) {
    if (typeof obj === 'object' && !Array.isArray(obj)) {
        let transformKey = (k) => [k, keepKeyOrder(obj[k])];
        return Object.keys(obj).map(transformKey);
    } else {
        return obj;
    }
};

console.log(keepKeyOrder({a:3,c:4,b:{b3:123,b2:234,b1:345}}));

输出:

在此处输入图片说明

另一个简单的解决方案是:

console.log(Object.entries(obj).map(k=>({[k[0]]:k[1]})))

只是为了澄清Console.log确实排序,但它也没有......

这是一个断点列表,正确的顺序(创建时)是default, mobileM, mobileL, tabletdesktopM这就是第一行中显示的内容。

在此处输入图片说明

但是当你展开它时,它们是按字母顺序排列的。如果您将鼠标悬停在某物上并查看弹出窗口,则相同。

关键是一分钟它确实对它们进行了排序,而下一分钟则没有。真的应该是一种选择,但似乎不是 - 如果您通常不关心财产秩序,这种混合行为真的会让您失望。