Array.prototype.sort()函数的一个属性是它是一种就地排序算法,这意味着它不会创建要排序的数组的新副本,它会在不使用任何额外空间的情况下对数组进行排序,从而使其更加高效和高效。但是这种特征有时会导致尴尬的情况。
让我们通过一个例子来理解这一点。假设,我们有一个包含一些字符串文字的names数组。我们希望保持该数组的顺序不变,并希望另一个数组包含与names数组相同的元素,但按字母顺序排序。
我们可以做这样的事情-
const names = ['Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj']; let sortedNames = names; sortedNames = sortedNames.sort(); console.log(names); console.log(sortedNames);
但是,正如我们在JavaScript中所知道的那样,数组也是对象,并且对象是通过引用而不是通过值复制的,因此对一个数组进行排序会导致对两个数组进行排序,这显然是我们不希望的。
解决方案
1.slice()
初始化新数组时使用
const names = ['Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj']; let sortedNames = names.slice(); sortedNames = sortedNames.sort(); console.log(names); console.log(sortedNames);
该slice()
方法实际上返回一个浅表副本,并复制到与其一起使用的数组的新数组中,如果未提供任何参数,它将从头到尾复制。
尽管此方法效率不高,因为它包括初始化一个新数组,并且仅对String / Number文字数组有效,但第二种方法效率更高,并且也适用于对象数组。
2.使用JSON.stringify()/ JSON.parse()
const names = ['Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj']; let sortedNames = JSON.parse(JSON.stringify(names)); sortedNames = sortedNames.sort(); console.log(names); console.log(sortedNames);
将数组转换为JSON字符串,然后转换回数组的方式会强制编译器不按引用复制。
这两种方法的输出在控制台中将相同-
输出结果
[ 'Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj' ] [ 'Anshul', 'Dheeraj', 'Mukesh', 'Rakesh', 'Ram' ]