关于javascript:JS的深浅复制原来如此

7次阅读

共计 2260 个字符,预计需要花费 6 分钟才能阅读完成。

摘要: 之所以会呈现深浅拷贝的问题,本质上是因为 JS 对根本类型和援用类型的解决不同。

本文分享自华为云社区《js 的深浅复制,一看就明确》,作者:鑫 2020。

浅复制的意思

浅复制是仅仅对数据寄存在栈内的援用的复制,没有复制援用指向堆内的内容。多个数据的浅复制,这复制多个援用,这多个援用独特指向堆内的同一个内容。当一个浅复制数据做出批改,即堆内的援用指向的内容产生批改,这时,其余通过援用指向这里的数据也会随着扭转。

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = obj;
objA.a = 'a';

console.log(obj.a);  // 'a'
console.log(objA.a);  // 'a'

深复制的意思

深复制是指连同堆的内容一块复制,生成一个新的对象。多个深复制将是多个不同的对象,也就有不同的援用,也就指向不同的堆内容。

应用深复制的原由

在平时开发中,有时会有数据的传递与接管,当拿到传过来的数据后,不免须要对数据进行加工和革新,为了不毁坏原有数据结构,这时就能够应用深复制拷贝数据,而后解决生成的新的数据。深复制也能够避免批改多个援用后援用凌乱的问题,缩小 BUG 的产生机会。

可实现深复制的几种办法

实现形式一:JSON 的序列化与反序列化

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = JSON.parse(JSON.stringify(obj));//JSON 的序列化与反序列化
objA.a = 'a';

console.log(obj.a);  // 1
console.log(objA.a);  // 'a'

尽管 JSON 的序列化与反序列化能够实现深复制,但有几个毛病须要留神:
1、date 日期对象被转成日期日期字符串
2、没法拜访到原型
3、复制不了 undefined 的属性
4、NAN 和无穷被转为 NULL

let d1 = new Date();
let obj = {
    d1,
    d2: undefined,
    d3:NaN
}
let objD = JSON.parse(JSON.stringify(obj));
console.log(obj) 
console.log(objD)

实现形式二:Object.assign()

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = Object.assign(obj);
objA.a = 'a';

console.log(obj.a);  // 1
console.log(objA.a);  // 'a'

尽管 Object.assign() 能够实现深复制,但对于更深层次的对象援用也是仅仅浅复制。

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = Object.assign(obj);
objA.c.c1 = 'c1'; //Object.assign() 仅仅是一层深复制。console.log(obj.c.c1);  // 'c1'
console.log(objA.c.c1);  // 'c1'

实现形式三:扩大运算符

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = {...obj};;
objA.a = 'a';

console.log(obj.a);  // 1
console.log(objA.a);  // 'a'

尽管扩大运算符 ”…” 能够实现深复制,但对于更深层次的对象援用也是仅仅浅复制。

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = {...obj};
objA.c.c1 = 'c1'; // 扩大运算符 "..." 同 Object.assign() 一样,仅仅是一层深复制,不能多层深复制。console.log(obj.c.c1);  // 'c1'
console.log(objA.c.c1);  // 'c1'

实现形式四:应用递归

想要实现深复制,且实现多层深复制则能够应用递归循环复制。

let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

const ReCopy = function (paramter) {
        let target = null;
        let isObject = paramter.constructor === Object;
        let isArray = paramter.constructor === Array;
        if (isObject || isArray) {target = Array.isArray(paramter) ? [] : {};
            for (let i in paramter) {target[i] = ReCopy(paramter[i]);
            }
        } else {target = paramter;}
        return target;
    }

let objA = ReCopy(obj);
objA.c.c1 = 'c1';

console.log(obj.c.c1);  // 10
console.log(objA.c.c1);  // 'c1'

ladash 深拷贝

lodash 深复制是更业余的深复制形式。

  • 装置 lodash

先初始化,生成 package.json 文件,而后应用一下命令装置。
npm i -S lodash

  • 引入 lodash
    var _ = require('lodash');
  • 应用 lodash
let obj = {
    a:1,
    b:2,
    c:{
        c1:10,
        c2:20
    }
}

let objA = _.cloneDeep(obj);
objA.c.c1 = 'c1'; 

console.log(obj.c.c1);  // 10
console.log(objA.c.c1);  // 'c1'

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0