1。数据的浅拷贝letobj={a:1,b:2,c:{d:99}};要复制当前obj,可以使用for循环依次复制它的keysvalue,也可以使用spread运算符。让newObj={...obj};newObj.c.d=100;console.log(obj);//{a:1,b:2,c:{d:100}}复制的值应该和旧值一样无关紧要,如果有关联,就是浅拷贝。这里修改了新值,同时也修改了旧值,说明在复制obj的时候,也复制了c属性的对象引用地址,导致新值修改了旧值的引用地址。这里可以再看一下数组的操作:letarr=[1,2,3,[4]];让newArr=arr.slice(0)newArr[3][0]=100;控制台日志(arr);//[1,2,3,[100]]用slice方法截取arr的所有值赋值给newArr。这里对新值的数组元素的操作也会影响到旧值,所以slice做的也是浅拷贝。2、实现深拷贝那么,我们如何实现深拷贝呢?1、校验当前数据类型2、数据循环引用以上两点是数据深拷贝的实现思路。首先需要判断数据的类型。常见的判断方式有:typeofObject.prototype.toString.callinstanceofconstructorIf当是基本数据类型(number、string、boolean、null、undefined)时,可以直接返回值;这里提到了null和undefined的类型校验,可以参考视频内容。如果是函数类型(function),可以直接返回函数,因为函数一般都是call-based。把函数转成字符串,复制返回还是这个函数;如果是内置对象实例,则根据其类新建一个,返回相应的对象即可;例如:RegExp、Date等。如果是数组或对象等引用类型,只要根据其构造函数创建对应的值并返回即可。({}).constructor//[Function:Object]([]).constructor//[Function:Array]可以直接根据其构造函数创建一个新值。创建新值后,新值与旧值无关。这时通过循环遍历旧值的索引或键,依次将值赋值给新值。附方法源码:functiondeepClone(value){if(value==undefined)returnvalue;if(typeofvalue!=='object')返回值;if(valueinstanceofRegExp)returnnewRegExp(value);if(valueinstanceofDate)returnnewDate(value);letinstance=newvalue.constructor;for(letkeyinvalue){if(value.hasOwnProperty(key)){//只复制私有属性instance[key]=deepClone(value[key]);}}返回实例;}
