//赋值1letobj1={a:1,b:2}letobj2=obj1obj2.a=3console.log(obj1)//?console.log(obj2)//?-//赋值2letobj1={a:1,b:2,c:{q:6}}letobj2=obj1obj2.a=3obj2.c.q=7console.log(obj1)//?console.log(obj2)//?-//浅拷贝1letobj1={a:1,b:2}letobj2=Object.assign({},obj1)obj2.a=3console.log(obj1)//?console.log(obj2)//?-//浅拷贝2letobj1={a:1,b:2,c:{q:6}}letobj2=Object.assign({},obj1)obj2.a=3obj2.c.q=7console.log(obj1)//?console.log(obj2)//?-//深拷贝let_=require('lodash');letobj1={a:1,b:2,c:{q:6}};letobj2=_.cloneDeep(obj1);obj2.a=3obj2.c.q=7console.log(obj1)//?console.log(obj2)//?JS数据类型及相关概念数据TypeJS有两种数据类型:基本类型和引用类型。基本类型:StringNumberBooleanundefinednullsymbol引用类型:ObjectArrayFunctionDate数据在内存中的存储当JS定义一个变量时,变量会被存储在内存栈中,但是基本类型和引用类型的存储方式不同:基本类型存储在栈内存中;引用类型存储在堆内存中,指向数据的指针(内存地址)存储在堆栈中。即:在定义一个新的变量来拷贝数据时,基本类型是拷贝原数据,而引用类型不是。正是因为这个问题,新手很容易遇到一个问题:复制一个对象(引用类型)后,修改新的对象,然后用原来的对象,发现原来的对象也变了。解决这个问题的方法就是学习赋值、浅拷贝和深拷贝的使用场景,灵活处理不同场景下的引用类型。对象赋值、浅拷贝、深拷贝赋值都不会创建新的对象,只是复制原对象的指针。浅拷贝就是创建一个新的对象。该对象仅复制原始对象的属性。当属性值为基本类型时,复制原始数据;当属性值是引用类型时,指针被复制。因此,如果原对象的属性有引用类型数据,那么无论你修改新对象的引用类型数据还是修改原对象的引用类型数据,对方都会相应改变。深拷贝也创建了一个新对象,但不仅复制了原对象的属性,还在堆内存中开辟了一个新的地址来存放新对象,因此新对象与原对象没有关联,修改一个其他的不会百变。QuestionAnswer//赋值1letobj1={a:1,b:2}letobj2=obj1obj2.a=3console.log(obj1)//{a:3,b:2}console.log(obj2)//{a:3,b:2}-//赋值2letobj1={a:1,b:2,c:{q:6}}letobj2=obj1obj2.a=3obj2.c.q=7console.log(obj1)//{a:3,b:2,c:{q:7}}console.log(obj2)//{a:3,b:2,c:{q:7}}-//浅拷贝1letobj1={a:1,b:2}letobj2=Object.assign({},obj1)obj2.a=3console.log(obj1)//{a:1,b:2}console.log(obj2)//{a:3,b:2}-//浅拷贝2letobj1={a:1,b:2,c:{q:6}}letobj2=Object.assign({},obj1)obj2.a=3obj2.c.q=7console.log(obj1)//{a:1,b:2,c:{q:7}}console.log(obj2)//{a:3,b:2,c:{q:7}}-//深度复制let_=require('lodash');letobj1={a:1,b:2,c:{q:6}};letobj2=_.cloneDeep(obj1);obj2.a=3obj2.c.q=7console.log(obj1)//{a:1,b:2,c:{q:6}}console.log(obj2)//{a:3,b:2,c:{q:7}}使用场景原对象只使用一次(修改无副作用),使用赋值。原始对象需要多次使用(修改会导致后续使用数据不准确),属性只有基本类型,没有引用类型,使用浅拷贝。原始数据需要多次使用(修改会导致后续使用数据不准确),属性中包含引用类型,所以使用深拷贝。浅拷贝Object.assign()的实现如上例,Object.assign()是浅拷贝concates5的浅拷贝方法扩展运算符es6的浅拷贝方法sliceJS数组的方法letarr1=[1,2,{username:'Kobe'}];letarr2=arr.slice();arr2[2].username='Wade'console.log(arr1[2]);//{用户名:'Kobe'}console.log(arr2[2]);//{username:'Wade'}lodash的clone()let_=require('lodash');letobj1={a:1,b:2,};varobj2=_.clone(obj1);手写实现functionshallowClone(source){vartarget={};for(variinsource){if(source.hasOwnProperty(i)){target[i]=source[i];}}returntarget;}letobj1={...}letobj2=shallowClone(obj1)深度复制JSON.parse(JSON.stringfy())letobj1={a:1,b:2}letobj2=的实现JSON.parse(JSON.stringify(obj1))注意:慎用,因为如果对象中有方法,深拷贝会丢失方法。例如:letobj1={a:1,b:2,c:function(){return'查看方法是否存在'}}letobj2=JSON.parse(JSON.stringify(obj1))console.log(obj1);//{a:1,b:2,c:?}console.log(obj2);//{a:1,b:2}lodash的deepClone()let_=require('lodash');letobj1={a:1,b:2,c:{q:6}};letobj2=_.cloneDeep(obj1);jquery.extend()//Usage:$.extend(deepCopy,target,object1,[objectN])//第一个参数为true,即深拷贝let$=require('jquery');让obj1={a:1,b:2,c:{q:6}};让obj2=$.扩展(真,{},obj1);手写体实现深拷贝的原理是递归遍历对象,直到只有基本类型再拷贝。点击阅读手写深拷贝代码
