实现浅拷贝
浅拷贝中,浅拷贝只是拷贝了它在栈中存储的指针,它们指向的都是同一个堆内存地址,所以浅拷贝在某些情况会造成改变数据后导致别的另一份数据也同步被改变的情况;
1.for...in...
手动实现浅拷贝只需for...in...循环把oldobj里元素值遍历赋值给进新对象;
2.object.assign()
深拷贝的实现
深拷贝是直接将堆内存中存储的数据直接复制一份,不会有浅拷贝互相影响的问题。
1.递归实现
let oldobj = { name: 'hxw', age: 21, hobby:['打篮球','踢足球','羽毛球'], bro:{ name:'fff', age:'21', hobby:['sing','dance'] } } function deepClone(obj){ if(typeof obj !== 'object' || obj == null){ return obj } let result; if(obj instanceof Array){ result = [] }else{ result = {} } for(let key in obj){ if(obj.hasOwnProperty(key)){ result[key] = deepClone(obj[key]) } } return result } let newobj = deepClone(oldobj) newobj.name = 'sd' newobj.bro.name = 'dsfasdf' console.log(newobj) console.log(oldobj)
手动实现深拷贝只需封装一个函数,做一个是否为对象或者数组的判断,如果是的话就进行递归,如果是其他值直接赋值即可。
2.JSON.parse(JSON.stringify())
将一个对象先转为json字符串,然后再转回来,这样可以实现深拷贝。
但是这个方法有个缺陷,可以实现对象或数组的深拷贝,但是不能处理函数,函数经过这样处理后会变成null。值为undefined,或者function的时候并不会拷贝过来。
3.jQuery的extend方法
/* $.extend( [deep ], target, object1 [, objectN ] ) deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝 target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。 object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。 */ let a = [0,1,[2,3],4], b = $.extend(true,[],a); a[0] = 1; a[2][0] = 1; console.log(a,b); // a = [1,1,[1,3],4]
4.使用lodash.cloneDeep实现深拷贝
import _ from 'lodash' var obj = {id:1,name:{a:'xx'},fn:function(){}}; var obj2 = _.cloneDeep(obj); obj2.name.a = 'obj2'; console.log(obj,obj2)
5.Structured Clone 结构化克隆算法
function structuralClone(obj) { return new Promise(resolve =>{ const {port1, port2} = new MessageChannel(); port2.onmessage = ev => resolve(ev.data); port1.postMessage(obj); }) } const obj = /* ... */; structuralClone(obj).then(res=>{ console.log(res); })