对 Javascript 对象中的键进行排序

IT技术 javascript sorting object key
2021-02-17 21:45:33

我有一个 Javascript 对象,它包含多种属性类型,包括简单的字符串、对象、对象数组……等等。

我想按照此规则对键进行排序:

'像字符串或数字这样的简单属性总是出现在包含数组或对象的更复杂的属性之前'

我编写了以下函数,几乎可以完成我想要实现的功能,但它将数组转换为对象。这不是理想的行为。谁能帮我创建一个函数,将数组保存为数组,同时对数组内的对象进行排序?

function sort(object){
    if (typeof object != "object" )
        return object;
    var keys = Object.keys(object);
    keys.sort(function(a,b){
            if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
        });

工作jsfiddle:

http://jsfiddle.net/u01mn2py/3/

亲切的问候

2个回答

从 ECMAScript 2015 (ES6) 开始,对象自己的属性确实对某些操作具有顺序,尽管依赖它很少是一个好主意。如果你想要顺序,通常最好使用数组或类似的。

顺序是:

  1. 成为一个新的空列表。
  2. 对于作为整数索引O 的每个自己的属性键P,按升序数字索引顺序
    • 添加P作为keys的最后一个元素
  3. 对于属于字符串但不是整数索引O 的每个自己的属性键P,按属性创建顺序
    • 添加P作为keys的最后一个元素
  4. 对于作为符号O 的每个自己的属性键P,按属性创建顺序
    • 添加P作为keys的最后一个元素
  5. 返回

那是“自己的”属性。我认为没有任何外部可用操作为所有属性(包括继承的属性)定义所需的顺序。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;
}

现场示例(我还更新了小提琴):

(您没有要求在类别内按字母顺序排列,但扔进去似乎是一件合理的事情。)

这在当前的 Chrome、Firefox 和 IE11 上对我有用。

@wildbyte:既然 ECMAScript 2015 已经完成,我已经更新了答案。
2021-04-20 21:45:33
我只需要将对象显示为有序的 JSON(按照我的规则),但 JSON.stringify 没有任何类型的排序选项。我怎样才能做到这一点?
2021-05-03 21:45:33
@wildbyte:对。属性在 JSON 中也没有顺序。如果您想要一个以特定顺序列出属性的 JSON 字符串,您必须构建自己的函数来执行此操作。(之前我不得不这样做,但遗憾的是不能共享该代码。但这并不是那么难,您可以使用其中JSON.stringify的一部分,但是您必须定义递归和迭代。大约需要 15 行代码.)
2021-05-09 21:45:33

我知道我无法传递 javascript 属性顺序,但我需要在视觉上显示排序的 JSON。以这种方式解决:

http://jsfiddle.net/u01mn2py/4/

function sort(object){
    if (typeof object != "object" ) // Not to sort the array
        return object;
    var keys = Object.keys(object);
    keys.sort(function(a,b){
            if (typeof(object[a])!== 'object') { return -1 } else { return 1 }
        });
    if( Object.prototype.toString.call( object ) === '[object Array]' ) {
        var newObject = [];
     } else {
        var newObject = {}; }

     for (var i = 0; i < keys.length; i++){
            newObject[keys[i]] = sort(object[keys[i]])
      }
    return newObject;
}