深拷贝和浅拷贝

108 阅读1分钟
浅拷贝:此处浅拷贝是针对对象的,因为如果是基本数据类型,直接赋值就可以拷贝。拷贝对象时,若属性是基本数据类型则拷贝值,若属性是引用数据类型,则拷贝地址值,但会导致修改新数据会同时修改原数据,因为新数据和原数据共享内存。
浅拷贝方法:

1、三点运算符:var copyarr=[...arr]

2、Object.assign方法:Object.assign(copyarr,arr1,arr2,...)

3、数组的Array.prototype.concat方法:var copyarr=arr.concat()

4、数组的Array.prototype.slice方法:var copyarr=arr.slice()


深拷贝:精确拷贝,深入拷贝到对象里的基本数据类型,从而当对象数据发生变化而不影响原数据
深拷贝方法

1、利用JSON

JSON.parse(JSON.stringify(obj/arr))

问题:

  • 若原数据包含函数,undefined,symbol等属性,拷贝后这些属性会消失
  • Date对象会变成String类型,RegExp对象会变成空对象{}
  • 对象中含有NaN、Infinity和-Infinity,拷贝后会变成null
  • 未拷贝对象的原型链

2、采用递归

简单版:只考虑数组和对象

function clone(obj){
    if(typeof obj === 'object'&&obj!==null){
       var newObj = Array.isArray(obj)?[]:{}
       for(const key in obj){
           newObj[key]=clone(obj[key])
       }
       return newObj
    }
    else return obj
}

问题:

  • 未拷贝正则对象和Date对象
  • for in可能会拷贝到原型对象的属性
  • 未继承原型链
优化
function clone(obj){
    if(obj instanceof RegExp){
        return new RegExp(obj)
    }
    else if(obj instanceof Date){
        return new Date(obj)
    }
    else if(obj instanceof Array){
        let newObj=[]
        obj.forEach((value)=>{
            newObj.push(clone(value))
        })
        return newObj
    }
    else if(obj instanceof Object){
        //拷贝原型链
        let newObj=new obj.contructor()
        for(let key in obj){
        	//判断是否是该对象上的属性,而非继承的属性
            if(obj.hasOwnProperty(key)){
                newObj[key]=clone(obj[key])
            }
        }
        return newObj
    }
    
    return obj
}

参考:www.jianshu.com/p/c651aeabf…