TypeScript中如何正确复制数组并修改元素且不影响原数组?
问题原因
你之前用的几种复制方式都是浅拷贝:虽然复制了外层数组和每个Span对象,但对象里的tags数组是引用类型,拷贝后新对象的tags和原对象的tags指向同一个内存地址。所以你修改copy[splitIndex].tags时,原props.value里对应的tags也会跟着变。
解决方案
需要对每个对象的tags数组也做一层拷贝,实现深拷贝到tags层级。修改复制数组的代码即可:
// 正确的拷贝方式:同时复制tags数组 let copy = props.value.map(a => ({ ...a, tags: [...a.tags] // 用扩展运算符复制tags数组,也可以用a.tags.slice()或Array.from(a.tags) }))
修改后的完整代码
type Span = { start: number end: number } // 补充包含tags的类型,避免使用as any type SpanWithTags = Span & { tags: string[] } const handleSplitClick = (span: Span, tag: string) => { // 拷贝外层数组+每个对象,同时复制tags数组 let copy = props.value.map((a: SpanWithTags) => ({ ...a, tags: [...a.tags] })) const splitIndex = copy.findIndex(s => s.start === span.start && s.end === span.end) if (splitIndex !== -1 ){ const targetSpan = copy[splitIndex] const tagIndex = targetSpan.tags.findIndex(t => t === tag) if (tagIndex > -1){ targetSpan.tags.splice(tagIndex, 1) console.log(copy) // 修改的是新数组的tags console.log(props.value) // 原数组的tags不受影响 } } }
额外说明
- 如果你的
Span对象还有更深层次的嵌套引用(比如tags里还有对象),那需要进一步深拷贝,但从场景看,tags是字符串数组,只需要拷贝这一层就够了。 - 尽量避免用
as any,通过定义SpanWithTags类型可以让代码更安全,减少类型错误。
内容的提问来源于stack exchange,提问作者Dim
相关产品推荐
相关产品推荐

