来个 js 大佬解释下这是 lodash 的 bug 吗?

直接上 代码吧,大概就是我项目中碰到的问题的一个缩影了

首先请大佬们 看下 打印结果 和你 预期的是不是相符

import { cloneDeep } from 'lodash'

const priceList = [1, 2]

const animals = { priceList }

const option = {
  series: ['dog', 'cat'].map(item => animals)
}

const o = cloneDeep(option) // 这里深拷贝了一个 option

o.series[0].priceList[0] = 5 // 我这里修改了series[0].priceList[0]的值 会不会影响 series[1].priceList的值?

console.log('o: ', o.series[0].priceList)
console.log('o: ', o.series[1].priceList)

结果是真的被修改了,是真的涉及到盲区了,我认为

const o = cloneDeep(option)

这行代码 不应该是把里面所有的引用类型 都深拷贝了一份吗?

为什么还是会被影响到?

阅读 2k
3 个回答

借用 @_usw 的回答,再补充一下吧
的确是有个 hashMap 存在的原因导致的
关键代码 应该是

if(map.get(data)) return map.get(data)
else map.set(target,data)

这两个 target 都是文中的 animals

所以第二个 serie 直接走了 map.get(target) 没有再做处理~

好像是因为lodash中在拷贝的时候为了防止循环引用,有一个stack会缓存拷贝结果。你的options.series实际上装了两个相同的引用,会满足stack的检查,复制的结果就是两个相同的引用,也符合目标的特征。因此不管是通过0元素还是通过1元素,修改的都是同一个对象

在克隆前和克隆后加了打印:

console.log(`option[0].series === option[1].series`, option.series[0] === option.series[1]);
const o = _.cloneDeep(option); // 这里深拷贝了一个 option
console.log(`o.series[0] === o.series[1]`, o.series[0] === o.series[1]);
console.log(`option.series[0] === o.series[0]`, option.series[0] === o.series[0]);

结果

option[0].series === option[1].series true
o.series[0] === o.series[1] true
option.series[0] === o.series[0] false

你看,没毛病啊,原来两个元素就是同一个对象的引用,所以克隆后他们两个元素还是同样的引用。
但是 option.series[0]o.series[0] 已经不是同一个对象了,确实是克隆的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题