347 字
2 分钟
Array.reduce() 会修改原数组!
get(index: number) {
// 先获取从0到index(包含index)的所有patch
const patches = this.patches.slice(0, index + 1);
// 从initialStage开始应用patch,得到在index时刻的舞台序列化数据
const data = patches.reduce((acc, patch) => {
return applyPatch(acc, patch).newDocument;
}, this.initialStage);
// 反序列化得到舞台对象
const stage = deserialize(data, this.project);
console.log("get %d = %o (patches %o)", index, stage, patches);
return stage;
}

这段代码用来获取在 index 时刻的舞台数据

看似没问题对吧,运行一下

Console
[INFO] get 0 = [ {} ] (patches: [
{ op: 'add', path: '/0', value: [ {} ] },
])
[INFO] get 0 = [ {}, {} ] (patches: [
{ op: 'add', path: '/0', value: [ {} ] },
])

诶,结果应该是一样的,为什么第二次运行结果多了一个 {}

参考 MDN「Array.prototype.reduce() # 有初始值时 reduce() 如何运行」

如果给 reduce() 提供了初始值引用,那么第一个参数提供的函数的返回值将会修改初始值

所以得拷贝一份 initialStage 作为初始值,以 lodash 为例

get(index: number) {
// 先获取从0到index(包含index)的所有patch
const patches = this.patches.slice(0, index + 1);
// 从initialStage开始应用patch,得到在index时刻的舞台序列化数据
const data = patches.reduce((acc, patch) => {
return applyPatch(acc, patch).newDocument;
}, _.cloneDeep(this.initialStage));
// 反序列化得到舞台对象
const stage = deserialize(data, this.project);
console.log("get %d = %o (patches %o)", index, stage, patches);
return stage;
}

这样就不会修改原数组了,问题解决

Array.reduce() 会修改原数组!
https://2y.nz/p/js-reduce-clone/
作者
zty012
发布于
2025-08-05
许可协议
CC BY-NC-SA 4.0