如何实现Array.prototype.sort默认比较功能?

时间:2017-11-16 16:07:57

标签: javascript sorting

背景

我需要实现一个与Array.prototype.sort的默认比较函数具有相同行为的函数

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

阅读完文档后,我偶然发现了这个:

  

默认排序顺序是根据字符串Unicode代码点。

这是什么意思?这是否意味着我将每个对象转换为字符串?

如果是这样,假设我有数组[2, "a", { hello: "world" }],这些步骤是否正确?

  1. [2, "a", { hello: "world" }]转换为["2", "a", '{ hello: "world" }']
  2. 将每个字符串的第一个字符转换为数字
  3. 按该号码订购
  4. 问题

    如何实现给定任何对象的比较函数,其行为与sort中的compare函数完全相同?

    备注

    阅读ECMA规范:

    我现在相信如果comparefnundefined,那么他们会将此算法用作默认值:

    http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare

    有人可以确认吗?

2 个答案:

答案 0 :(得分:0)

看起来><就足够了。

你可以看看我做了一段时间的implementation of Array.prototype.sort。它可能会帮助您了解您的需求。

答案 1 :(得分:0)

解决方案

在阅读了ECMA规范并四处询问之后,我到达了defaultCompare函数,该函数模拟了chrome中Array.prototype.sort()的默认行为:

const defaultCompare = ( x, y ) => {
    //INFO: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
    //ECMA specification: http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare

    if( x === undefined && y === undefined )
        return 0;

    if( x === undefined )
        return 1;

    if( y === undefined )
        return -1;

    const xString = toString(x);
    const yString = toString(y);

    if( xString < yString )
        return -1;

    if( xString > yString )
        return 1;

    return 0;
};

const toString = obj => {
    //ECMA specification: http://www.ecma-international.org/ecma-262/6.0/#sec-tostring

    if( obj === null )
        return "null";

    if( typeof obj === "boolean" ||  typeof obj === "number" )
        return (obj).toString();

    if( typeof obj === "string" )
        return obj;

    if( typeof obj === "symbol" )
        throw new TypeError();

    //we know we have an object. perhaps return JSON.stringify?
    return (obj).toString();
};

module.exports = defaultCompare;

我该如何测试?

您可以像下面这样测试此功能:

const arr = [ undefined, null, 3, 2, ‘B’, ‘a’, ‘b’, ‘A’,
{ hello: “world”}, { goodnight: ‘moon’} ]

assertEql( arr.sort(). arr.sort(defaultCompare) ); //true

如果您在同一浏览器中测试它们,输出应该相等。