前言
客官老爷们都知道,深拷贝、浅拷贝是面试中逢考必问的高频知识点,日常学习中也大多碰到过,所以今天咱们就浅讲一下它们的几种实现方法吧
浅拷贝
- 浅拷贝的定义:
自己创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。总而言之,完成拷贝后可能存在彼此之间操作互相影响的就是浅拷贝。
- 实现浅拷贝的几种方式
-
Array.prototype.slice
使用数组的slice()方法可以实现浅拷贝,但使用场景比较少const arr = [1, 2, {name: 'zs'}]; const newArr = arr.slice(); newArr[2].name = 'ls'; -
Array.prototype.concat
concat()方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。 它其实也可以用来实现浅拷贝
const arr = [1, 2, {name: 'zs'}]; const newArr = arr.concat(); newArr[2].name = 'ls'; console.log(arr); console.log(newArr);- Object.assign
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。它是开发阶段最常使用到用以浅拷贝的方法let target = { a:{ b:{ c:1, d:2 }, e:3, d:4, f:5 } } let souce = { a:{ b:{ c:1, d:2 }, e:3, d:4 } } Object.assign(target,souce) console.log(target); //{ a: { b: { c: 1, d: 2 }, e: 3, d: 4 } } f属性并没有复制过去 souce.a.b.c = 10 console.log(target.a.b.c); //10 对象target里c的值也发生了改变 ```
-
深拷贝
- 深拷贝的定义
深拷贝:完成拷贝后彼此之间操作绝不会有互相影响的就是深拷贝。
- 实现深拷贝的两种方法
- 使用
JSON.stringify()方法和JSON.parse()方法实现深拷贝
let obj1 = { name:'zs', age:18 } let obj = JSON.stringify(obj1) // JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串 obj1.age = 30 let str = JSON.parse(obj) //JSON.parse() 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象 obj1.age = 33 console.log(str);//{name: 'zs', age: 18}- 自己封装一个深拷贝函数
function checkValue(val) { // 通过这个方法来获取数据的类型 typeof关键字不能判断引用数据类型 // console.log(Object.prototype.toString.call(val).slice(8, -1)); return Object.prototype.toString.call(val).slice(8, -1) } //console.log(checkValue(function () {})); //console.log(checkValue([]); //console.log(checkValue({}); function deepClone(target) { let targetType = checkValue(target) let reslut if (targetType === 'Object') { reslut = {} } else if (targetType === 'Array') { reslut = [] } else { return reslut } // 遍历引用数据类型 for (const key in target) { if (Object.hasOwnProperty.call(target, key)) { const element = target[key]; // 检查属性值的数据类型 let valueType = checkValue(element) if (valueType === 'Object' || valueType === 'Array') { // 如果对象或者数组里的属性值也是引用数据类型的话 进行递归 reslut[key] = deepClone(element) } else { // 将值添加进对象中 reslut[key] = element } } } return reslut } // 测试数组 let arr1 = [1, 2, { age: 18 }] let arr2 = deepClone(arr1) arr2[2].age = 33 console.log(arr1); //[ 1, 2, { age: 18 } ] //arr1 arr2 互不影响 //测试对象 let obj1 = { name: 'zs', age: 18, hobbies: [1, 2, { age: 18 }] } let obj2 = deepClone(obj1) obj1.name = 123 obj1.hobbies[2].age = 30 console.log(obj1);//{ name: 123, age: 18, hobbies: [ 1, 2, { age: 30 } ] } console.log(obj2);//{ name: 'zs', age: 18, hobbies: [ 1, 2, { age: 18 } ] } //obj1 obj2 互不影响 - 使用
总结
1. 定义
浅拷贝:完成拷贝后可能存在彼此之间操作互相影响的就是浅拷贝。
深拷贝:完成拷贝后彼此之间操作绝不会有互相影响的就是深拷贝。
2.浅拷贝和深拷贝的区别
1、浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
2、深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
3、浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的数据都会拷贝出来。
感言
说来惭愧,本萌新学习前端已有一年多了,这还是第一次写文章,也算是从0到1的突破吧。不过文笔有点稀碎,还请客官们见谅啊。才疏学浅,文章如有问题,可以一起在评论区讨论一二哟。最后望诸君共勉,你学费了吗
参考文档
- 橘右溪-浅拷贝的五种实现方式
- imooc 谢成老师的es6视频
- b站pink老师