辨析浅拷贝与深拷贝
浅拷贝:浅拷贝是把一个对象内容或地址给另一个对象,他们指向相同,两对象有共同属性和方法(一块内存中内容赋值一份给另一块内存)。
深拷贝:深拷贝是把一个对象中的属性和方法找到,在另一个对象中开辟相应的空间,一个个存储在另一个对象中。
*深拷贝与浅拷贝的区别?
浅拷贝:指向的是同一块内存地址,当一个发生变化时另一个也跟着变;
深拷贝:在计算机中开辟出一块新的内存地址用于存放复制的对象;
实现:
浅拷贝:
(1)对象中:
Object.assign()
let a = { name: 'zhangsan', }; let b = Object.assign({},a); a.name = 'wangwu'; console.log('a==', a, 'b===', b); //a== {name: "wangwu"} b=== {name: "zhangsan"}
扩展运算符
let a = { name: 'zhangsan', }; let c = { ...a }; a.name = 'wangwu'; console.log(c);//{name: "zhangsan"}
(2)数组中:
数组有两个方法 concat 和 slice 是可以实现对原数组的拷贝的,这两个方法都不会修改原数组,而是返回一个修改后的新数组。(浅拷贝,即都只对数组的第一层进行深拷贝)
注意:浅拷贝只解决了第一层的问题,如果对象中还有嵌套对象就需要使用深拷贝。
深拷贝:
JSON.parse(JSON.stringify(object))
let obj = { name: 'yangyi', age: 23, likes: { type: 1, width: 200, height: 300, }, }; let objs = JSON.parse(JSON.stringify(obj)); obj.likes.type = 2; console.log('obj===', obj, 'objs==', objs); //obj.likes.type=2,objs.likes.type=1
注意:该方法也是有局限性的(由于它是依赖于JSON,而JSON只支持object,array,string,number,true,false,null这几种数据或者值,其他的比如函数,undefined,Date,RegExp等数据类型都不支持。对于它不支持的数据都会直接忽略该属性。):
- 会忽略undefined
- 不能序列化函数
- 不能解决循环引起的对象
- 不能拷贝正则表达式
- Date类型数据会被转化为字符串类型(丢失Date的一些特性,比如时间格式化等方法)
实现一个完整的深拷贝:
deepCopy = (target) => { if (typeof target !== 'object') return; let dist={}; if(target instanceof Array){ // 拷贝数组 dist = []; }else if(target instanceof Function){ // 拷贝函数 dist = function () { return target.call(this, ...arguments); }; }else if(target instanceof RegExp){ // 拷贝正则表达式 dist = new RegExp(target.source,target.flags); }else if(target instanceof Date){ dist = new Date(target); }else{ // 拷贝普通对象 dist = {}; } for(let key in target){ if(target.hasOwnProperty(key)){ dist[key]=typeof target[key]==='object'?this.deepCopy(target[key]):target[key]; } } return dist; };