请教个 JavaScript 问题

2021-05-08 15:50:20 +08:00
 MonkeyD1
function bubbleSort(arr, b) {
let newArr = arr.map(v => v),max = newArr.length - 1;
for (let j = 0; j < max; j++) {
for (let i = 0; i < max - j; i++) {
if (newArr[i].id > newArr[i + 1].id) {
let temp = newArr[i].id;
newArr[i].id = newArr[i + 1].id;
newArr[i + 1].id = temp;
}
}
}
return newArr;
}

let arr = [{ id: 4 }, { id: 2 }, { id: 3 }, { id: 9 }];

console.log(arr); // [{id: 2},{id: 3},{id: 4},{id: 9}]
console.log(bubbleSort(arr)); // [{id: 2},{id: 3},{id: 4},{id: 9}]
console.log(arr); // [{id: 2},{id: 3},{id: 4},{id: 9}]

排序 为什么原始的 arr 也被修改了
1602 次点击
所在节点    JavaScript
10 条回复
JK9993
2021-05-08 16:00:00 +08:00
因为你修改的是对象的 id,而不是交换新数组里元素的位置。新数组里的对象引用的还是原来的。另外当前场景下 Array.prototype.slice 比 map 更合适
MonkeyD1
2021-05-08 16:00:23 +08:00
大意了 我自己发的帖子 我自己也不能删😑
MonkeyD1
2021-05-08 16:04:38 +08:00
@JK9993 感谢🤦‍♂️, 我以为 有一层 map 已经拷贝了 没想到里面的对象 拷贝的还是指针 我去看看 slice
MonkeyD1
2021-05-08 16:11:48 +08:00
已解决 let newArr = JSON.parse(JSON.stringify(arr));
liyang5945
2021-05-08 16:15:11 +08:00
newArr = arr.concat()
MonkeyD1
2021-05-08 16:17:00 +08:00
@liyang5945 不行的噢 需要深拷贝
liyang5945
2021-05-08 16:26:17 +08:00
@MonkeyD1 #6 上面那句就是深拷贝,不会改变原数组,你可以试下
chogath
2021-05-08 16:26:54 +08:00
JSON.parse(JSON.stringify(object)) 存在一些不足,例如:

1. 拷贝的对象的值中如果有函数, undefined, symbol,则经过 JSON.stringify() 序列化后的 JSON 字符串中这个键值对会消失
2. 无法拷贝不可枚举的属性,无法拷贝对象的原型链
3. 拷贝 Date 引用类型会变成字符串
4. 拷贝 RegExp 引用类型会变成空对象
5. 无法拷贝对象的循环引用(即 obj[key] = obj)

所以还是建议你直接手写,或者用第三方库,例如:lodash.cloneDeep
christin
2021-05-08 17:48:34 +08:00
@liyang5945
concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
concat 并不是深拷贝 而是返回新数组

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
christin
2021-05-08 17:50:09 +08:00
@christin 所以才不会改变原数组

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/775666

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX