浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
浅拷贝的实现方式
直接赋值一个变量
1 | let obj = {username: 'kobe', age: 39, sex: {option1: '男', option2: '女'}}; |
Object.assign()
1 | let obj = { |
Array.prototype.concat()
1 | let arr = [1, 3, { |
修改新对象会改到原对象:
Array.prototype.slice()
1 | let arr = [1, 3, { |
同样修改新对象会改到原对象:
关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。详细规则请看MDN对应函数讲解。
深拷贝的实现方式
JSON.parse(JSON.stringify())
1 | let arr = [1, 3, { |
原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
这种方法虽然可以实现数组或对象深拷贝,但不能处理函数
1 | let arr = [1, 3, { |
这是因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数
手写递归方法(含hasOwnProperty)
1 | function inCopy(obj1,obj2) { |
在进行深拷贝的时候,我们首先需要提出原型对象上的属性;通过hasOwnProperty方法来进行筛选,所有继承了 Object 的对象都会继承到 hasOwnProperty 方法。这个方法可以用来检测一个对象是否含有特定的自身属性;和 in 运算符不同,该方法会忽略掉那些从原型链上继承到的属性。
函数库lodash
该函数库也有提供_.cloneDeep用来做 Deep Copy
1 | var _ = require('lodash'); |