Swift 4 如何按值复制数组?修改新数组对象不影响原数组
如何实现数组中对象的按值复制(深拷贝)
问题的核心在于:数组里的对象是引用类型,普通的浅拷贝(比如arr.slice()或者[...arr])只会复制数组本身的结构,但数组里的对象仍然指向同一个内存地址——所以修改arr2里的对象时,原数组arr里的对象也会跟着变。要做到修改arr2不影响arr,你需要对数组里的每个对象进行深拷贝,也就是完全复制对象的所有层级的属性,而不是只复制引用。
下面是几种常用的实现方式:
1. 快速方案:JSON.parse(JSON.stringify())
这是最常用的“懒人方法”,适合对象结构简单、没有特殊类型(比如函数、undefined、循环引用、Date、RegExp)的场景:
var arr = [{ name: "Alice", age: 30 }]; // 深拷贝数组及其中的对象 var arr2 = JSON.parse(JSON.stringify(arr)); // 修改arr2里的对象 arr2[0].age = 31; console.log(arr[0].age); // 输出30,原数组完全不受影响
⚠️ 注意局限性:
- 如果对象里包含函数、
Symbol、undefined,这些值会被直接忽略 - 如果存在循环引用(比如对象的某个属性指向自身),这个方法会抛出错误
- 对于
Date对象,会被转成字符串,而不是保留Date类型
2. 自定义递归深拷贝函数
如果你的对象有复杂的嵌套结构,或者包含特殊类型,自己写一个递归函数来处理会更灵活:
function deepCopy(target) { // 处理基本类型和null的情况,直接返回原值 if (target === null || typeof target !== 'object') { return target; } // 处理数组:遍历每个元素递归拷贝 if (Array.isArray(target)) { return target.map(item => deepCopy(item)); } // 处理普通对象:遍历所有自有属性递归拷贝 const copiedObj = {}; for (const key in target) { if (target.hasOwnProperty(key)) { copiedObj[key] = deepCopy(target[key]); } } // 如果你需要处理Date、RegExp等特殊对象,可以在这里添加分支 // 比如处理Date: // if (target instanceof Date) { // return new Date(target.getTime()); // } return copiedObj; } // 示例使用 var arr = [{ name: "Bob", hobbies: ["reading", "hiking"] }]; var arr2 = deepCopy(arr); arr2[0].hobbies.push("coding"); console.log(arr[0].hobbies); // 输出["reading", "hiking"],原数组未被修改
这个方法可以根据你的需求扩展,比如添加对Date、RegExp、Map、Set等特殊类型的处理逻辑。
3. 第三方库方案:Lodash的_.cloneDeep
如果你的项目已经引入了Lodash库,直接使用_.cloneDeep是最省心的选择——它已经帮你处理了几乎所有的边界情况,包括循环引用、特殊对象类型等:
// 确保已经引入Lodash(比如通过npm安装或CDN引入) var arr = [{ name: "Charlie", info: { job: "developer" } }]; var arr2 = _.cloneDeep(arr); arr2[0].info.job = "designer"; console.log(arr[0].info.job); // 输出"developer",原数组不受影响
总结
- 简单场景用
JSON.parse(JSON.stringify()),快速便捷 - 复杂场景或需要自定义处理特殊类型时,使用递归深拷贝函数
- 项目已有Lodash时,优先用
_.cloneDeep,减少自己造轮子的成本
内容的提问来源于stack exchange,提问作者AlexP
相关产品推荐
相关产品推荐

