.sort函数会改变原始数组吗?

54

我有这段代码:

arr = arr.sort(function (a, b) {
    return a.time>b.time
})

我需要重新定义 arr 数组吗,还是直接调用排序函数就可以了?像这样:

arr.sort(function (a, b) {
    return a.time>b.time
})

排序和过滤函数会改变原始数组吗?


1
我已经尝试过了,但有时候我不明白为什么它不起作用。我的代码有问题还是我误用了 .sort 函数? - Prosto Trader
2
两者都可以工作,因为sort会改变数组。但是比较函数将基于(+n, 0, -n)的返回值而不是布尔值来工作。请更改比较器。 - Kamrul
我真的不明白问题出在哪里,但是是可以使用 === 运算符在排序之前和之后进行测试的东西。 - Alexander Mills
1
我发现这里的答案非常不令人满意,因此我添加了一个我认为更好的答案。 - Alexander Mills
6个回答

75

使用slice()对原始数组进行副本的排序。

var arr =[{time:4},{time:3},{time:6}];

arr.sort(function (a, b) {
  return a.time-b.time;
});

会改变原始数组并返回:

[ { time: 3 }, { time: 4 }, { time: 6 } ]

而 console.log(arr) 返回的是:

[ { time: 3 }, { time: 4 }, { time: 6 } ]

但是

var arr =[{time:4},{time:3},{time:6}];
arr.slice().sort(function (a, b) {
  return a.time-b.time;
});

返回

[ { time: 3 }, { time: 4 }, { time: 6 } ]

但不会影响原始数组。

console.log(arr) 返回

[ { time: 4 }, { time: 3 }, { time: 6 } ]


23

这是一个不错的问题,让我们来认真回答一下:

const a = [1, 2, 3];
const b = a.sort();
console.log(a === b); // true

这是你的答案。对象的===运算符将比较内存位置,因此在内存中是相同的对象。

这有点可惜,因为如果sort创建一个新数组(不变性等),那就更好了,但在许多语言中它并不会返回一个新数组,而是返回相同的数组(重新排序)。

因此,如果您希望它是不可变的,可以这样做:

const a = [1, 2, 3];
const b = a.slice(0).sort();

5
是的!sort() 会改变原始数组。而 filter() 函数则创建一个过滤后的副本,不会影响原始数组。详情请见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter 。 - Bill B
1
实际上,我相当喜欢它改变原始数据的特性。因为这样,你可以处理和解决问题。但是如果不能自动更新现有引用,你就无法解决“我想让这个数组排序,以便现有引用获取更新后的数据”的问题。想象一下,如果arr.push(4,5,6)不改变原始数据,那将是一场噩梦。你只能完全依赖arr = arr.concat([4,5,6]),但仍然无法更新引用。 - RoboticRenaissance

10

它会就地排序数组(修改数组)。来自 MDN

sort() 方法在原数组上对其元素进行排序,并返回排序后的数组。这种排序不一定稳定。默认排序顺序是根据字符串 Unicode 代码点。


sort 的一个有趣特性是 "未定义的属性值总是排在结果的末尾,其后是不存在的属性值", 因此它有效地将稀疏数组转换为紧凑数组但保持原始长度。 - RobG

5

是的,它修改了原始数组。

const a = [1, 2, 3];
const b = a.sort();
const c = [...a].sort(); //es6 feauture similar to slice(0)
console.log(a === b); // true
console.log(a === c);//false

我更喜欢这个,我认为它比splice().sort()性能更好。 - fatiu

1

或者从ES6开始:

const a = [1, 2, 3];
const b = [...a].sort();

1

排序和过滤功能会改变原始数组吗?

对于 sort() 方法,答案是 是的,但对于 filter() 方法,答案是 不会

让我用一个例子来解释 :

// Original Array
const arr = [5, 4, 3, 2, 1];

// Sorting array values and assigned in a variable.
const sortedArr = arr.sort((a, b) => a-b);

// Original array modified.
console.log(arr); // [1,2,3,4,5]

// New variable with sorted array.
console.log(sortedArr); // [1,2,3,4,5]

为了防止修改原始数组,我们可以使用to[操作]方法,它返回一个应用了该操作的新集合(目前处于第三阶段,即将可用)。
const arr = [5, 4, 3, 2, 1];

const sortedArr = arr.toSort((a, b) => a-b);

console.log(arr); // [5, 4, 3, 2, 1]

console.log(sortedArr); // [1, 2, 3, 4, 5]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接