什么是深拷贝与浅拷贝?深拷贝与浅拷贝是js中处理对象或数据复制操作的两种方式。在聊深浅拷贝之前咱得了解一下js中的两种数据类型:
前言
什么是深拷贝与浅拷贝?深拷贝与浅拷贝是js中处理对象或数据复制操作的两种方式。在聊深浅拷贝之前咱得了解一下js中的两种数据类型:
基本数据类型(6种)
String、Number、Object、Boolean、null、undefined、symbol(ES6+)
引用数据类型
Object(function、Array、正则表达式等皆是对象)
基本数据: 基本数据类型是存放在栈中的简单数据段,它们是直接按值存放的,所以可以直接按值访问
引用类型: 引用类型是存放在堆内存中的对象,保存的在栈内存中的一个指针,保存的是栈内存中对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。
1.浅拷贝
1.1 什么是浅拷贝
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址。
- 下面用一张图来解释一下浅拷贝
1.2 浅拷贝实现方法
1.2.1 assign
| var obj = { |
| age: 18, |
| person: { |
| name1: 'fx', |
| name2: 'xka' |
| }, |
| list:['hhh','666'], |
| love: function () { |
| console.log('嘿嘿') |
| } |
| } |
| var newObj = Object.assign({}, obj); |
| |
| obj.person.name1='xxx' |
| obj.list[0]='xxx' |
| console.log(newObj.person.name1) |
1.2.2 slice
| const fxArr = ["One", { |
| name: "Two", |
| age: 20 |
| }, "Three"] |
| const fxArrs = fxArr.slice(0,) |
| fxArr[1].name = "four"; |
| console.log(fxArrs[1].name) |
1.2.3 concat
| const fxArr = ["One", { |
| name: "Two", |
| age: 20 |
| }, "Three"] |
| const fxArrs = fxArr.concat() |
| fxArr[1].name = "four"; |
| console.log(fxArrs[1].name) |
1.2.4 拓展运算符
| const fxArr = ["One", { |
| name: "Two", |
| age: 20 |
| }, "Three"] |
| const fxArrs = [...fxArr] |
| fxArr[1].name = "four"; |
| console.log(fxArrs[1].name) |
2.深拷贝
2.1 什么是深拷贝
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
- 下面用一张图来解释一下深拷贝
2.2 浅拷贝实现方法
2.2.1 JSON.parse(常用)
| var obj = { |
| age: 18, |
| person: { |
| name1: 'fx', |
| name2: 'xka' |
| }, |
| list:['hhh','666'], |
| love: function () { |
| console.log('嘿嘿') |
| } |
| } |
| |
| const obj2=JSON.parse(JSON.stringify(obj)); |
| obj.person.name1='6666' |
| console.log(obj2.person.name1) |
- 我常用的基本就是JSON.parse了,然而其他的,之前听过的lodash的cloneDeep,jq的extend我都没使用过。
- 但是适用JSON.parse会有一个缺点,就是处理的数据里面有undefined、function、symbol会被忽略,但是这也是一个优点,可以利用其特性将undefined等数据排除,拿到干净的数据。还有一个缺点就是在处理的数据比较大的话,还有性能问题。
3.手写实现深浅拷贝
3.1 浅拷贝
| function clone(object){ |
| const newObj={} |
| for(let proto in object){ |
| if(object.hasOwnProperty(proto)){ |
| newObj[proto]= object[proto] |
| } |
| } |
| return newObj |
| } |
| var obj = { |
| age: 18, |
| person: { |
| name1: 'fx', |
| name2: 'xka' |
| }, |
| list:['hhh','666'], |
| love: function () { |
| console.log('嘿嘿') |
| } |
| } |
| |
| const obj1=clone(obj) |
| console.log(obj) |
| console.log(obj1) |
3.2 深拷贝
| |
| function deepClone(obj, hash = new WeakMap()) { |
| |
| if (obj === null) return obj; |
| if (obj instanceof Date) return new Date(obj); |
| if (obj instanceof RegExp) return new RegExp(obj); |
| |
| |
| if (typeof obj !== "object") return obj; |
| |
| if (hash.get(obj)) return hash.get(obj); |
| |
| |
| |
| let cloneObj = new obj.constructor(); |
| hash.set(obj, cloneObj); |
| for (let key in obj) { |
| if (obj.hasOwnProperty(key)) { |
| |
| cloneObj[key] = deepClone(obj[key], hash); |
| } |
| } |
| return cloneObj; |
| } |
| var obj = { |
| age: 18, |
| person: { |
| name1: 'fx', |
| name2: 'xka' |
| }, |
| list:['hhh','666'], |
| love: function () { |
| console.log('嘿嘿') |
| } |
| } |
| |
| |
| const obj2 = deepClone(obj) |
| const obj3 = Object.assign({}, obj) |
| const obj4 = clone(obj) |
| obj.person.name1 = 'hhh'; |
| |
| console.log(obj2.person.name1) |
| |
| console.log(obj3.person.name1) |
| console.log(obj4.person.name1) |
上述为个人学习整理内容,水平有限,如有错误之处,望各位园友不吝赐教!如果觉得不错,请点击推荐和关注!谢谢~๑•́₃•̀๑ [鲜花][鲜花][鲜花]