提问人: 提问时间:12/21/2016 更新时间:12/21/2016 访问量:102
为什么这个函数会改变数据?
Why does this function mutate data?
问:
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 设置为等于该变量。我觉得自己像个白痴,但我不知道为什么会这样:(
答:
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
您需要克隆原始数组以避免原始数组中发生更改。克隆可以通过使用
- slice() 原型方法。
- 循环。
- Array.from() 中。
- 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);
评论
let sort = toSort.slice();