在JavaScript编程中,我们经常需要处理对象和数组的复制操作。深拷贝和浅拷贝是两种常见的复制方式,它们在实现上有着不同的特点和应用场景。本文将介绍在复制操作中常见深浅拷贝的区别与实现方式。

1.深浅拷贝的区别

共同点:都是进行复制操作。
浅拷贝:只复制引用,而未复制真正的值。
深拷贝:完全拷贝一份新的对象,会在堆内存中开辟新的空间,拷贝的对象被修改后,原对象不受影响。
使用 “=” 进行直接赋值操作时,基本数据类型为深拷贝,引用数据类型为浅拷贝。

2.深浅拷贝的实现方式

1.ES6扩展运算符

const obj = { name: 'luaox', age: 23, fn:()=>{} }
const objCopy1 = { ...obj }
objCopy1.age = 18
console.log(obj);  // {name: 'luaox', age: 23, fn: ƒ}
console.log(objCopy1);  // {name: 'luaox', age: 18, fn: ƒ}

特点:只能实现一维对象或一维数组的深拷贝,可以拷贝内部函数。

2.Object.assign方法

const obj = { name: 'luaox', age: 23, fn:()=>{} }
const objCopy2={}
Object.assign(objCopy2,obj)
objCopy2.age = 18
console.log(obj);  // {name: 'luaox', age: 23, fn: ƒ}
console.log(objCopy2);  // {name: 'luaox', age: 18, fn: ƒ}

特点:只能实现一维对象的深拷贝,可以拷贝内部函数。

3.Array.prototype.concat方法

const arr =[1,2,3,4]
const arrCopy1=[].concat(arr)
arrCopy1[0]=10
console.log(arr);  // [1, 2, 3, 4]
console.log(arrCopy1);  // [10, 2, 3, 4]

特点:只能实现一维数组的深拷贝,可以拷贝内部函数。
以上三种方法都是只能实现一维上的深拷贝,如果对象或数组嵌套层数过多,以上方法均不适用。

4.JSON.parse(JSON.stringify())方法

const obj={name:'luaox',age:18,hobby:['唱','跳'],fn:()=>{}}
const objCopy=JSON.parse(JSON.stringify(obj))
objCopy.hobby[1]='篮球'
console.log(obj);
console.log(objCopy);


特点:对于多层嵌套的数组或对象仍可进行深拷贝,但不会拷贝内部函数。

5.递归函数实现深拷贝

function deepCopy(obj){
    let newObj=obj instanceof Array?[]:{}
    for(let key in obj){
        let value=obj[key]
        newObj[key]=(value!==null && typeof value==='object')?deepCopy(value):value
    }
    return newObj
}

const obj = { name: 'luaox', age: 18, hobby: ['唱', '跳',['书','画']], fn: () => {console.log(1); } }
const objCopy=deepCopy(obj)
objCopy.hobby[2][0] = 'rap'
console.log(obj);
console.log(objCopy);


特点:自定义编写函数方法显得更为灵活,但要考虑到更多的特殊情况。

6.lodash库

lodash是一套工具库,可以通过script标签直接引入或使用npm进行下载导入,其内部封装了很多字符串、数组、对象等常见数据类型的处理函数。其中cloneDeep方法内部实现了深拷贝。

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script>
    const obj = { name: 'luaox', age: 18, hobby: ['唱', '跳', ['书', '画']], fn: () => { console.log(1); } }
    // 语法:_.cloneDeep(要被克隆的对象)
    const objCopy = _.cloneDeep(obj)
    objCopy.hobby[2][0] = 'rap'
    console.log(obj);
    console.log(objCopy);
</script>

特点:简单方便。