理解浅拷贝和深拷贝js中的数据可以大致分为两种类型基本数据类型和引用数据类型。基本数据类型基本数据类型的变量的赋值可理解为深拷贝修改其中一个数据另一个数据不会随之变化引用数据类型引用数据类型分为key和value它们两个分开存储数据的值value在内存中而指针key指向内存中的value值引用数据类型的数据进行赋值其实只是拷贝了数据的指针key两个key指向的是同一个内存中的同一个值修改其中一个指针对值的修改另一个数据的值也会随着更改。浅拷贝方法浅拷贝拷贝的是地址如果有对象嵌套深层对象就会存在修改覆盖的问题数组的slice(start,end)数组的concat方法运用展开运算符推荐Object.assign()var a1 {name yiyi, age: 18}; var a2 Object.assign({}, a1); a2.name test; console.log(a1);//{name yiyi, age: 18} console.log(a2);//{name test, age: 18} //展开运算符 //我们也可以使用ES6的写法 var a3 {name yiyi, age: 18}; var a4 {...a3}; a4.name test2; console.log(a3);//{name yiyi, age: 18} console.log(a4);//{name test2, age: 18}//concat() var a1 [1,2,3]; var a2 a1.concat(); a1[0] 2; console.log(a1);// [2,2,3] console.log(a2);//[1,2,3] //展开运算符 //我们也可以使用ES6的写法 var a1 [2,2,2]; var a2 [...a1]; a1[0] 1; console.log(a1);// [1,2,2] console.log(a2);//[2,2,2] //slice() var a1 [3,4,5]; var a2 a1.slice(); a1[0] 1; console.log(a1);// [1,4,5] console.log(a2);//[3,4,5]如何实现浅拷贝function shallowCopy(obj) { // 排除非对象或 null 的情况 if (typeof obj ! object || obj null) return obj; // 判断是数组还是普通对象创建对应的新容器 const newObj Array.isArray(obj) ? [] : {}; // 遍历并复制自身的可枚举属性 for (let key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] obj[key]; } } return newObj; }深拷贝方法JSON.stringify()对简单的对象深拷贝不能拷贝具有方法Symbol和不可枚举对象等var o1 {a: 1, b: 2, c: 3, family: {child: child}}; var o2 JSON.parse(JSON.stringify(o1)); o1.a 2; o2.family.child child2 console.log(o1); //{2,2,3, family: {child: child}} console.log(o2);//{1,2,3, family: {child: child2}}JQuery库中的extend方法$.extend( [deep ], target, object1 [, objectN ] )object1 需要被合并的对象deep表示是否进行深拷贝target 合并后到该对象上var o1 {a: 1, b: 2, c: 3}; var o2 $.extend(true,{},o1); o1.a 2; console.log(o1); //{2,2,3} console.log(o2); //{1,2,3}如何实现深拷贝function deepClone(obj, hash new WeakMap()) { // 1. 处理基本类型和 null if (obj null || typeof obj ! object) return obj; // 2. 处理特殊内置对象如 Date、RegExp if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags); // 3. 解决循环引用如果该对象已经被拷贝过直接返回缓存 if (hash.has(obj)) return hash.get(obj); // 4. 根据原型创建对应的新容器保持数组或普通对象的类型 const cloneObj Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj)); // 5. 存入缓存防止后续递归产生死循环 hash.set(obj, cloneObj); // 6. 递归拷贝所有自身属性包括 Symbol 属性 Reflect.ownKeys(obj).forEach(key { cloneObj[key] deepClone(obj[key], hash); }); return cloneObj; } // 测试循环引用 const original { a: 1, b: { c: 2 } }; original.self original; // 自己指向自己 const copy deepClone(original); console.log(copy.self copy); // 输出: true ✅ 完美处理循环引用简单介绍到这里哈哈哈这些真的是简单好用的方法适合日常使用关于多级对象和方法的拷贝以后再整理
浅谈浅拷贝和深拷贝
发布时间:2026/5/26 17:30:03
理解浅拷贝和深拷贝js中的数据可以大致分为两种类型基本数据类型和引用数据类型。基本数据类型基本数据类型的变量的赋值可理解为深拷贝修改其中一个数据另一个数据不会随之变化引用数据类型引用数据类型分为key和value它们两个分开存储数据的值value在内存中而指针key指向内存中的value值引用数据类型的数据进行赋值其实只是拷贝了数据的指针key两个key指向的是同一个内存中的同一个值修改其中一个指针对值的修改另一个数据的值也会随着更改。浅拷贝方法浅拷贝拷贝的是地址如果有对象嵌套深层对象就会存在修改覆盖的问题数组的slice(start,end)数组的concat方法运用展开运算符推荐Object.assign()var a1 {name yiyi, age: 18}; var a2 Object.assign({}, a1); a2.name test; console.log(a1);//{name yiyi, age: 18} console.log(a2);//{name test, age: 18} //展开运算符 //我们也可以使用ES6的写法 var a3 {name yiyi, age: 18}; var a4 {...a3}; a4.name test2; console.log(a3);//{name yiyi, age: 18} console.log(a4);//{name test2, age: 18}//concat() var a1 [1,2,3]; var a2 a1.concat(); a1[0] 2; console.log(a1);// [2,2,3] console.log(a2);//[1,2,3] //展开运算符 //我们也可以使用ES6的写法 var a1 [2,2,2]; var a2 [...a1]; a1[0] 1; console.log(a1);// [1,2,2] console.log(a2);//[2,2,2] //slice() var a1 [3,4,5]; var a2 a1.slice(); a1[0] 1; console.log(a1);// [1,4,5] console.log(a2);//[3,4,5]如何实现浅拷贝function shallowCopy(obj) { // 排除非对象或 null 的情况 if (typeof obj ! object || obj null) return obj; // 判断是数组还是普通对象创建对应的新容器 const newObj Array.isArray(obj) ? [] : {}; // 遍历并复制自身的可枚举属性 for (let key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] obj[key]; } } return newObj; }深拷贝方法JSON.stringify()对简单的对象深拷贝不能拷贝具有方法Symbol和不可枚举对象等var o1 {a: 1, b: 2, c: 3, family: {child: child}}; var o2 JSON.parse(JSON.stringify(o1)); o1.a 2; o2.family.child child2 console.log(o1); //{2,2,3, family: {child: child}} console.log(o2);//{1,2,3, family: {child: child2}}JQuery库中的extend方法$.extend( [deep ], target, object1 [, objectN ] )object1 需要被合并的对象deep表示是否进行深拷贝target 合并后到该对象上var o1 {a: 1, b: 2, c: 3}; var o2 $.extend(true,{},o1); o1.a 2; console.log(o1); //{2,2,3} console.log(o2); //{1,2,3}如何实现深拷贝function deepClone(obj, hash new WeakMap()) { // 1. 处理基本类型和 null if (obj null || typeof obj ! object) return obj; // 2. 处理特殊内置对象如 Date、RegExp if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags); // 3. 解决循环引用如果该对象已经被拷贝过直接返回缓存 if (hash.has(obj)) return hash.get(obj); // 4. 根据原型创建对应的新容器保持数组或普通对象的类型 const cloneObj Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj)); // 5. 存入缓存防止后续递归产生死循环 hash.set(obj, cloneObj); // 6. 递归拷贝所有自身属性包括 Symbol 属性 Reflect.ownKeys(obj).forEach(key { cloneObj[key] deepClone(obj[key], hash); }); return cloneObj; } // 测试循环引用 const original { a: 1, b: { c: 2 } }; original.self original; // 自己指向自己 const copy deepClone(original); console.log(copy.self copy); // 输出: true ✅ 完美处理循环引用简单介绍到这里哈哈哈这些真的是简单好用的方法适合日常使用关于多级对象和方法的拷贝以后再整理