为什么运行顺序Javascript sort()函数会影响第一个函数的输出?

时间:2019-03-03 11:01:49

标签: javascript arrays

我正在努力解决Wes Bos Javascript 30的数组有氧运动挑战,并且正在努力理解sort()函数在一起运行或顺序运行时的行为。

我们从一系列发明者对象开始,最初的挑战是按生日排序。

初始函数(orderBirth)按计划工作,并返回按预期排序的数组。

然后,我们编写另一个函数(最旧的)以按发明人的年龄对发明人数组进行排序。再次按预期工作。

但是,如果我重新运行console.log(orderBirth),它将返回按年龄而不是生日排序的数组。

我知道sort函数会更改原始数组(对其进行突变),但我不明白为什么这样做会阻止orderBirth函数在第二次运行时正常工作。

const inventors = [
      { first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
      { first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
      { first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
      { first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
      { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
      { first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 },
      { first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
      { first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
      { first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
      { first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
      { first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
      { first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
    ];
    
const orderBirth = inventors.sort((a, b) => a.year > b.year ? 1 : -1);
    
console.log('Ordered by birthdate table')
console.log(orderBirth)

const oldest = inventors.sort((a, b) => {
      const lastInventor = a.passed - a.year;
      const nextInventor = b.passed - b.year;
      return lastInventor > nextInventor ? -1 : 1;
    });

console.log('Ordered by age')
console.log(oldest);

console.log('Re-running orderBirth gives unexpected result')
console.log(orderBirth)

我已经阅读了does-sort-function-change-original-array的帖子,但这虽然解释了sort函数的就地变异,但并不能回答我的问题。或者至少它不能用我目前对JS的理解水平来回答。

4 个答案:

答案 0 :(得分:1)

Sort改变了原始数组。因此,当您顺序使用sort时,最终将一次又一次地更改同一数组。

let arr = [1,2,3,5,6,64,76,52]

arr.sort((a,b)=> a-b)

console.log(arr)

您可以创建数组副本,然后对其进行排序

let arr = [1,2,3,5,6,64,76,52]

let arr2 = [...arr].sort((a,b)=> a-b)

console.log(arr,arr2)

答案 1 :(得分:1)

在JS中,数组名称仅存储对原始数组的引用。然后对数组进行排序(更改)。您没有使用

复制数组
  

const orderBirth = investors.sort((a,b)=> a.year> b.year?1:-1);

相反,您要存储对按年份排序的数组的引用。

当您再次使用其他功能进行排序时,主数组将更改。而且orderBirth仍指向它。因此,情况也会发生变化。

编辑:如Scorpioo590所说,.slice()方法将复制该数组。

  

const orderBirth = creator.slice()。sort((a,b)=> a.year> b.year?1:-1);

以这种方式正确实现了您假设'='运算符的操作。

答案 2 :(得分:1)

sort使原始数组变异并返回排序后的数组。因此,它们都指向内存中的同一阵列。这两个都将返回true

console.log(inventors === orderBirth)
console.log(oldest === orderBirth)

const inventors=[{first:'Albert',last:'Einstein',year:1879,passed:1955},{first:'Isaac',last:'Newton',year:1643,passed:1727},{first:'Galileo',last:'Galilei',year:1564,passed:1642},{first:'Marie',last:'Curie',year:1867,passed:1934},{first:'Johannes',last:'Kepler',year:1571,passed:1630},{first:'Nicolaus',last:'Copernicus',year:1473,passed:1543},{first:'Max',last:'Planck',year:1858,passed:1947},{first:'Katherine',last:'Blodgett',year:1898,passed:1979},{first:'Ada',last:'Lovelace',year:1815,passed:1852},{first:'Sarah E.',last:'Goode',year:1855,passed:1905},{first:'Lise',last:'Meitner',year:1878,passed:1968},{first:'Hanna',last:'Hammarström',year:1829,passed:1909}]
    
const orderBirth = inventors.sort((a, b) => a.year > b.year ? 1 : -1);

const oldest = inventors.sort((a, b) => {
      const lastInventor = a.passed - a.year;
      const nextInventor = b.passed - b.year;
      return lastInventor > nextInventor ? -1 : 1;
    });

console.log(inventors === orderBirth)
console.log(oldest === orderBirth)

答案 3 :(得分:1)

正如您提到的,sort函数会更改原始数组。

const orderBirth = inventors.sort(...)得到数组的引用。这意味着两个变量实际上都指向内存中的同一位置。因此,在更改原始数组时,您还更改新变量。 您将需要创建原始数组的副本以保留排序结果。

const orderBirth = inventors.sort(...).slice();

应该可以解决问题。