为什么这个函数会改变数据?

Why does this function mutate data?

提问人: 提问时间:12/21/2016 更新时间:12/21/2016 访问量:102

问:

function bubbleSort(toSort) {
  let sort = toSort;
  let swapped = true;
  while(swapped) {
    swapped = false;
    for(let i = 0; i < sort.length; i++) {
      if(sort[i-1] > sort[i]) {
        let temp = sort[i-1];
        sort[i-1] = sort[i];
        sort[i] = temp;
        swapped = true;
      }
    }
  }
  return sort;
}

let asdf = [1,4,3,2];
let asd = bubbleSort(asdf);

console.log(asdf, asd);

此代码的输出为:[ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]。

我所期望的: [ 1, 4, 3, 2 ] [ 1, 2, 3, 4 ]。

我想知道的是,为什么这会改变 asdf 变量?bubbleSort 函数接受给定的数组 (asdf),复制它 (sort),然后处理该变量并返回它,asd 设置为等于该变量。我觉得自己像个白痴,但我不知道为什么会这样:(

JavaScript的 不变性 可变

评论

0赞 Jaromanda X 12/21/2016
复制数组, - 参见 stackoverflow.com/questions/518000/...let sort = toSort.slice();
0赞 vijay 12/21/2016
请参考此 stackoverflow.com/questions/41255297/...

答:

5赞 Paul 12/21/2016 #1

bubbleSort 函数接受给定的数组 (asdf),复制它 (sort)

不,它没有。赋值不会创建对象的副本,而是创建对现有对象的另一个引用。

复制数组的一种简单方法是使用 Array.prototype.slice

  let sort = toSort.slice( 0 );

有关复制对象的更多信息,请参阅:如何正确克隆 JavaScript 对象?

1赞 Jaxon 12/21/2016 #2

您正在对作为可变函数参数给出的输入列表进行排序。当您将列表分配给新变量时,它不会创建“副本”,它只是创建指向同一列表、相同数据的另一个引用,然后您继续进行排序。这就是为什么 asdf 和 add 变量是相同的,因为它们是指向相同内存位置、相同数据的两个变量。

如果您希望复制数组以不修改输入数组,请查看 javascript slice() 方法。

0赞 vijay 12/21/2016 #3

您需要克隆原始数组以避免原始数组中发生更改。克隆可以通过使用

  1. slice() 原型方法。
  2. 循环
  3. Array.from() 中。
  4. concat() 中。

替换为 或let sort = toSort;let sort = toSort.slice(0);

 let sort=[];
  for(var i=0;i < toSort.length;i++){
  sort[i]=toSort[i];  
  }

  let sort = Array.from(toSort);

let sort = toSort.concat();

function bubbleSort(toSort) {
  let sort = toSort.slice(0);
  let swapped = true;
  while (swapped) {
    swapped = false;
    for (let i = 0; i < sort.length; i++) {
      if (sort[i - 1] > sort[i]) {
        let temp = sort[i - 1];
        sort[i - 1] = sort[i];
        sort[i] = temp;
        swapped = true;
      }
    }
  }
  return sort;
}

let asdf = [1, 4, 3, 2];

let asd = bubbleSort(asdf);

console.log(asdf, asd);