从 ECMAScript 2015 (ES6) 开始,对象自己的属性确实对某些操作具有顺序,尽管依赖它很少是一个好主意。如果你想要顺序,通常最好使用数组或类似的。
顺序是:
- 让键成为一个新的空列表。
- 对于作为整数索引的O 的每个自己的属性键P,按升序数字索引顺序
- 对于属于字符串但不是整数索引的O 的每个自己的属性键P,按属性创建顺序
- 对于作为符号的O 的每个自己的属性键P,按属性创建顺序
- 返回键。
那是“自己的”属性。我认为没有任何外部可用操作为所有属性(包括继承的属性)定义所需的顺序。(for-in不需要遵循上面的顺序,即使在 ES2015+ 中也不需要。)从 ES2019 开始,for-in 确实有一个定义的顺序 (有一些例外)。
这意味着如果我们的键都不符合整数索引的条件,则可能可以在兼容引擎上执行您的要求。
JSON 仍然没有顺序,但JSON.stringifyJavaScript 规范要求使用上述顺序。
我不是说我建议它。:-)
function sort(object) {
// Don't try to sort things that aren't objects
if (typeof object != "object") {
return object;
}
// Don't sort arrays, but do sort their contents
if (Array.isArray(object)) {
object.forEach(function(entry, index) {
object[index] = sort(entry);
});
return object;
}
// Sort the keys
var keys = Object.keys(object);
keys.sort(function (a, b) {
var atype = typeof object[a],
btype = typeof object[b],
rv;
if (atype !== btype && (atype === "object" || btype === "object")) {
// Non-objects before objects
rv = atype === 'object' ? 1 : -1;
} else {
// Alphabetical within categories
rv = a.localeCompare(b);
}
return rv;
});
// Create new object in the new order, sorting
// its subordinate properties as necessary
var newObject = {};
keys.forEach(function(key) {
newObject[key] = sort(object[key]);
});
return newObject;
}
现场示例(我还更新了小提琴):
function sort(object) {
// Don't try to sort things that aren't objects
if (typeof object != "object") {
return object;
}
// Don't sort arrays, but do sort their contents
if (Array.isArray(object)) {
object.forEach(function(entry, index) {
object[index] = sort(entry);
});
return object;
}
// Sort the keys
var keys = Object.keys(object);
keys.sort(function (a, b) {
var atype = typeof object[a],
btype = typeof object[b],
rv;
if (atype !== btype && (atype === "object" || btype === "object")) {
// Non-objects before objects
rv = atype === 'object' ? 1 : -1;
} else {
// Alphabetical within categories
rv = a.localeCompare(b);
}
return rv;
});
// Create new object in the new order, sorting
// its subordinate properties as necessary
var newObject = {};
keys.forEach(function(key) {
newObject[key] = sort(object[key]);
});
return newObject;
}
var object = {
family: [{
home: {
city: 'Madrid'
},
birth: {
city: 'Madrid'
},
name: 'John',
age: 32
}, {
home: {
city: 'London'
},
birth: {
city: 'Paris'
},
name: 'Marie',
age: 25
}],
name: 'Dani',
age: 33
};
var sortedObject = sort(object);
document.getElementById('container').innerHTML = JSON.stringify(sortedObject, null, '\t');
<pre id="container">
</pre>
(您没有要求在类别内按字母顺序排列,但扔进去似乎是一件合理的事情。)
这在当前的 Chrome、Firefox 和 IE11 上对我有用。