夜下客

繁体版 简体版
夜下客 > JS修炼法则 > 第26章 真的理解V8的sort吗

第26章 真的理解V8的sort吗

一.前言

上一篇 blog 005 V8的sort实现中,我们简单聊了聊,引擎中的排序算法的思想和实践。但具体细节我们其实没有展开。

本文中,我们直接来 sort 函数相关的 JS实践 。

二.sort()默认函数

你猜下面函数的运行结果是什么?

[7,-2,2,-7,-3].sort()

// 会是 [-7, -3, -2, 2, 7] 吗?

下面来揭晓答案!

肯定不会符合你的预期啦!

答案是:

[-2, -3, -7, 2, 7]

为什么呢?

官方定义,MDN Array.prototype.sort(),sort()方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。

arr.sort(compareFunction)

// compareFunction: 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的 Unicode 位点进行排序。

// 返回值: 排序后的数组。请注意,数组已原地排序,并且不进行复制。

定义略微有点长,且晦涩。

通俗点说,sort() 默认等价于sort((a,b)=>a.toString().localeCompare(b))。

MDN String.prototype.localeCompare(): 如果引用字符存在于比较字符之前则为负数; 如果引用字符存在于比较字符之后则为正数; 相等的时候返回 0 .

我们来解释下上面的案例:

对于V8来说,-7,它会理解成两个token:-、7。

-的码点是在数字之前的,所以负数一定在最前方,即 数组前三位一定是-2,-3,-7。

码点感兴趣的可以阅读 阮一峰 Unicode与JavaScript详解

接下来我们看一下顺序,都有- ,可以忽略,简化为2,3,7 比较顺序,所以顺序就是2,3,7

最后排好顺序,再加上-即可。

所以,解决方案:

[7,-2,2,-7,-3].sort((x, y) => x - y)

// [-7, -3, -2, 2, 7]

所以,基于这个,在看个例子

[1, 111, 2, 3].sort() // [1, 111, 2, 3]

'1'.localeCompare('111') // -1

'2'.localeCompare('111') // 1

因为我们提到 compareFunction: 如果省略,元素按照转换为的字符串的各个字符的 Unicode 位点进行排序.

111和2比较,前者第一个字符1的码点位于后者前面,所以111在2前面。

三.sort(compareFunction)的compareFunction

下面的代码,我们希望运行结果应该是: 连续的数字升序排列。

var arr = [

{value: 3},

{value: undefined},

{value: 2},

{value: undefined},

{value: 5},

{value: 1},

{value: undefined},

{value: 4}

];

res = arr.sort((x, y) => x.value - y.value).map(x => x.value);

console.log(res);

它会符合预期吗?

显然不会。

真实运行结果是:

// [ 3, undefined, 2, undefin

『加入书签,方便阅读』