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

时间:2016-12-21 04:50:28

标签: javascript immutability mutable

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),复制它(排序),然后处理该变量并返回它,asd设置为等于。我觉得自己像个白痴,但我不知道为什么会这样:(

3 个答案:

答案 0 :(得分:5)

  

bubbleSort函数接受给定数组(asdf),复制它(排序)

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

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

  let sort = toSort.slice( 0 );

有关复制对象的更多信息,请参阅:How do I correctly clone a JavaScript object?

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

完成
  1. 切片()原型方法。
  2. 即可。
  3. Array.from()即可。
  4. 的concat()即可。
  5. 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();
    

    &#13;
    &#13;
    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);
    &#13;
    &#13;
    &#13;