当前位置: 首页 > Web前端 > HTML

js深浅拷贝排列

时间:2023-03-29 12:09:56 HTML

浅拷贝Object.assignobject.assign语法为:Object.assign(target,...sources)Object.assignfeatures不会拷贝对象的继承属性;枚举属性;可以复制符号类型的属性。扩展操作符方法扩展操作符的语法是:letcloneObj={...obj};扩展操作符的拷贝方式类似于Object.assign,只是浅拷贝。如果属性都是值的基本类型,使用扩展操作可以很方便的对字符进行浅拷贝。concat复制数组letarr=[1,2];letnewArr=arr.concat();newArr[1]=10;console.log(arr);//[1,2]console.log(newArr);//[1,10]slice的使用有局限性。复制数组切片的语法是:arr.slice(begin,end);会在不改变原数组的情况下返回一个新的数组,只能复制一层对象,嵌套类型什么也做不了。实现浅拷贝的思路是:对基本类型做一个基本拷贝;为引用类型开辟一个新的存储空间,复制一层对象属性。functionshallowClone(target){if(typeoftarget==='object'&&target!==null){constclone=Array.isArray(target)?[]:{}for(letiintarget){if(target.hasOwnProperty(i)){clone[i]=target[i]}}returnclone;}else{returntarget}}deepcopy深拷贝原理:将内存中的一个对象完整复制到目标对象中,并从堆内存中开辟新的空间存放新对象,新对象的修改不会改变原始对象,两者实现真正的分离JSON.stringify这个方法比较常用,也比较好用letobj1={a:1,b:[1,2,3]}letstr=JSON.stringify(obj1);让obj2=JSON.parse(str);type,JSON.stringify序列化后的字符串中的键值对将消失;复制Date引用类型将成为一个字符串;不能复制不可枚举的属性;不能复制对象的原型链;复制RegExp引用类型将成为一个空对象;如果对象中包含NaN、Infinity、-Infinity,则JSON序列化结果为null;对象的循环引用不可复制,即对象形成一个环(obj[key]=obj)。递归复制在实际应用中比较常见,这种方式用的比较多functiondeepClone(obj){letclone={};for(letkeyinobj){if(typeofobj[key]==="object"){clone[key]=deepClone(obj[key])}else{clone[key]=obj[key]}}返回clone;}有个问题这个深拷贝函数不能拷贝不可枚举的属性和Symbol类型;this这个方法只针对普通引用类型的值进行递归复制,但是对于Array、Date、RegExp、Error、Function等引用类型,是无法正确复制的;对象的属性存在循环,即没有解决循环引用。改进版的深拷贝解决了上述拷贝存在的问题。改进版增加了新的加工项目。对于不可枚举的属性和可以遍历的Symbol类型,我们可以使用Reflect.ownKeys方法;当参数为Date和RegExp类型时,直接生成新的实例并返回;使用Object的getOwnPropertyDescriptors方法可以获取对象的所有属性和相应的特征,并通过Object的create方法创建一个新的对象,并继承原对象的原型链;使用WeakMap类型作为Hash表,因为WeakMap是弱引用类型,可以有效防止内存泄漏(大家可以注意Map和weakMap的关键区别,这里用的是weakMap),对于检测循环很有帮助参考。如果有循环,则引用直接返回存储在WeakMap中的值。Reflect.ownKeys方法返回目标对象自身属性键的数组。它的返回值相当于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。目的。获取自己的属性描述符。该方法的主要作用是返回属性的描述对象(descriptor)。WeakMap与Map类似,但也有区别:1.WeakMap只接受对象作为键。如果设置其他类型的数据为key,会报错。2、WeakMap的key引用的对象都是弱引用。只要删除对该对象的其他引用,垃圾回收机制就会释放该对象占用的内存,从而避免内存泄漏。3、由于WeakMap的成员随时可能被垃圾回收机制回收,成员数量不稳定,所以没有size属性。4.没有clear()方法5.无法遍历代码实现//判断是否为复杂数据类型constisComplexDataType=obj=>{(typeofobj==="object"||typeofobj==="function")&&(obj!==null)}constdeepClone=function(obj,hash=newWeakMap()){//特殊对象处理if(obj.constructor===Date)returnnewDate(obj)if(obj.constructor===RegExp)returnnewRegExp(obj)//如果有循环引用,用WeakMap解决if(hash.get(obj))returnhash.get(obj)letallDesc=Object.getOwnPropertyDescriptors(对象);//遍历passLetclone=Object.create(Object.getPrototypeOf(obj),allDesc)//继承原型链hash.set(obj,clone)for(letkeyofReflect.ownKeys(obj)){clone[key]=(isComplexDataType(obj[key])&&typeofobj[key]!=="函数")?deepClone(obj[key],hash):obj[key]}返回克隆}