深拷贝、浅拷贝的区别?如何实现深拷贝和浅拷贝?
基本类型的数据赋值后,更改赋值后的变量,两者互不影响
let a = 100; let b = a; a = 200; console.log(a); // 200 console.log(b); // 100
引用类型的数据赋值后,将存放在栈内存中的地址赋值给新变量,更改赋值后的变量会影响到原数据
// 复杂数据类型:Array、Object let obj1 = { name:"小李", age:18 } let obj2 = obj1 obj1.age = 25; console.log( obj1 ); // {name:"小李", age:25} console.log( obj2 ); // {name:"小李", age:25}
深浅拷贝的目的就是原对象改变不影响新拷贝对象的结果
浅拷贝
定义:
- 创建一个新对象,这个对象有着原始数据值的一份拷贝
- 如果是基本数据类型,拷贝的就是基本类型的值
- 如果是引用数据类型,拷贝的就是内存地址,如果改变了这个地址就会影响到另一个对象
浅拷贝只能实现一层的拷贝,无法实现深层次的拷贝
实现方法:
Object.assign()第一个参数是拷贝目标,剩下的参数是拷贝的源对象(可以是多个)
let obj1 = { name: "小李", age: 18 } // Object.assign() 会返回一个新对象 // 这种写法和下面写法实现效果一样 // let obj2 = Object.assign({}, obj1) let obj2 = {} Object.assign(obj2, obj1) obj1.name = '小张'; obj1.age = '25'; console.log(obj1); // {name:"小张", age:25} console.log(obj2); // {name:"小李", age:18}
contact()合并两个或多个数组,返回一个新数组。原数组不变
let arr = [1,2,3,4]; let newArr = arr.concat() arr.push(5); console.log(arr); // [1,2,3,4,5] console.log(newArr ); // [1,2,3,4]
扩展运算符(如果对象中的属性都是基本数据类型的话,使用扩展运算符更加方便)
let obj1 = { name: "小李", age: 18 } let obj2 = {...obj1} obj1.name = '小张'; obj1.age = '25'; console.log(obj1, obj2); let arr = [1, 2, 3] let newArr = [...arr] arr[0] = 999 console.log(arr, newArr)
深拷贝
不管原数据内的值是什么类型,新拷贝的数据和原数据都是相互独立的,没有关联
实现方法
利用josn数据和josn字符串之间的转换(无法拷贝对象中的方法)
JSON.stringify()
将对象转换成JSON字符串
JSON.parse()
反序列化将JSON字符串变成一个新的对象
let obj1 = { name: "小李", age: 18, father: { age: 40 }, fn: function () { return 123 } } let temp = JSON.stringify(obj1) let obj2 = JSON.parse(temp) obj1.father.age = 50; console.log(obj1); // {name:"小李", age:18, father:{age:50},fn()} console.log(obj2); // {name:"小张", age:25, father:{age:40}} console.log(obj2.fn) // underfind
$.extend()
jQuery.extend([deep], target, object1, [objectN])
deep默认为false;
target新的对象
object1及后面的为要拷贝的对象
// 注意要引入jQuery的CDN才能使用该方法 let obj1 = { name: "小李", age: 18, father: { age: 40 }, fn: function () { return 123 } } let obj2 = $.extend(true, {}, obj1) obj1.father.age = 50; console.log(obj1,obj2);
递归
function deepClone(obj) { // 定义一个对象,用来确定当前的参数是数组还是对象 let objClone = Array.isArray(obj) ? [] : {}; // 判断obj是否存在,且类型是对象。(typeof [] 也是 object) if (obj && typeof obj === "object") { // 遍历参数的键 for (key in obj) { // hasOwnProperty() 方法不会检测对象的原型链,只会检测当前对象本身存在该属性时才返回 true,常与for...in使用 // 判断对象是否存在该属性 if (obj.hasOwnProperty(key)) { // 值是对象就递归 if (obj[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key]); } else { // 基本数据类型 直接赋值 objClone[key] = obj[key]; } } } } return objClone; } let a = { name: "小李", age: 18, father: { name: "大李", }, fn: function () { return 123 } } let b = deepClone(a) a.father.name = "小李他爸" console.log(a, b);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构