ES6中数组和对象的扩展运算符拷贝问题以及常用的深浅拷贝方法

时间:2019-11-10
本文章向大家介绍ES6中数组和对象的扩展运算符拷贝问题以及常用的深浅拷贝方法,主要包括ES6中数组和对象的扩展运算符拷贝问题以及常用的深浅拷贝方法使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

  在ES6中新增了扩展运算符可以对数组和对象进行操作。有时候会遇到数组和对象的拷贝,可能会用到扩展运算符。那么这个扩展运算符到底是深拷贝还是浅拷贝呢?

一.、使用扩展运算符拷贝

  首先是下面的代码。

let a = [1,2,3];
let b = [...a];
a == b // false

  结果是false,这是很容易知道的,毕竟这个赋值操作符是由区别的。接下来将数组的只进行改变,又会怎样呢;

let a = [1,2,3];
let b = [...a];
a[0] = 11;
console.log(a); // [ 11, 2, 3 ]
console.log(b); // [ 1, 2, 3 ]

  发现a的值发生改变之后b的值并没有发生改变。所以就是深拷贝了吗?别急,接下来将数组中的元素设为引用类型。

let a = [1,2,[1,2,3]];
let b = [...a];
a[2][1] = 11;
console.log(a); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] === b[2]); // true
 

  这次的结果就有意思了,如果改变数组中的引用类型的元素中的值,此时a和b的值都会改变,并且a和b中的引用类型全等,也就是说地址是相同的。那么为什么是这样的呢?

二.、原因

  首先此分析仅为本人目前的认知。

  对于数组中的扩展运算符只是一个浅拷贝,仅对引用类型数据的第一层进行了拷贝,而倘若再深的层次就不会进行拷贝。

  另外对象的扩展运算符和数组是一样的。

let a = {
    name : "Jyy",
    msg : {
        age : 29
    }
}
let b = {...a};
console.log(a == b);    // false
console.log(a.msg == b.msg);    // true;
a.msg = {
    age : "28"
}
console.log(a); // { name: 'Jyy', msg: { age: '28' } }
console.log(b); // { name: 'Jyy', msg: { age: 29 } }

三、深拷贝和浅拷贝的方法

  1.浅拷贝方法

    上面的例子已经看出来es6中的扩展运算符仅仅对引用类型进行了第一层的拷贝。除了es6的扩展运算符还有其他方法

    对象:

      使用Object.assign()

        Object.assign()用于对象的合并,如果第一个参数为{},则可对后面的对象参数进行拷贝

let a = {
    name : "Jyy",
    msg : {
        age : 29
    }
}
let b = Object.assign({},a);
console.log(a == b);    // false
console.log(a.msg == b.msg);    // true;
a.msg = {
    age : "28"
}
console.log(a); // { name: 'Jyy', msg: { age: '28' } }
console.log(b); // { name: 'Jyy', msg: { age: 29 } }

    数组: 

      数组的浅拷贝的方法很多

      a.使用slice()

        slice可以截取数组中部分的元素,若参数为空,则可对数组进行浅拷贝

let a = [1,2,[1,2,3]];
let b = a.slice();
console.log(a == b);    // false
a[2][1] = 11;
a[0] = 11;
console.log(a); // [ 11, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] == b[2]);  // true

      b.使用concat()

        concat可以对数组进行合并,若参数为空,亦可对数组进行浅拷贝

let a = [1,2,[1,2,3]];
let b = a.concat();
console.log(a == b);    // false
a[2][1] = 11;
a[0] = 11;
console.log(a); // [ 11, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] == b[2]);  // true

      c.使用Array.from()

let a = [1,2,[1,2,3]];
let b = Array.from(a);
console.log(a == b);    // false
a[2][1] = 11;
a[0] = 11;
console.log(a); // [ 11, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] == b[2]);  // true

  2.深拷贝

    对于深拷贝,数组和对象的方法是一致的

    a.递归方法,就是用for循环一层一层的进行拷贝,具体代码就不写了

    b.JSON.parse()

      这个方法通常用于调用接口传参或者是返回的字符串数据转成对象。

let a = {
    name : "JYY",
    age : "25",
    msg : {
        addr : "hebei"
    }
}
b = JSON.parse(JSON.stringify(a));
console.log(a == b);    // false
console.log(a.msg == b.msg);    // false
a.msg.addr = "chengde";
console.log(a); // { name: 'JYY', age: '25', msg: { addr: 'chengde' } }
console.log(b); // { name: 'JYY', age: '25', msg: { addr: 'hebei' } }

      这个方法的弊端就是undefinedfunctionsymbol 会在转换过程中被忽略

let a = {
    name : "JYY",
    age : "25",
    msg : {
        addr : "hebei"
    },
    speek : function(){
        console.log(this.name);
    }
}
b = JSON.parse(JSON.stringify(a));
console.log(a); // { name: 'JYY', height: Symbol(jyy), age: undefined, msg: { addr: 'chengde' },speek: [Function: speek] }
console.log(b); // { name: 'JYY', msg: { addr: 'hebei' } }

    c.使用第三方插件

      比如lodash的深拷贝

const _ = require("lodash");
let syb = Symbol('jyy');
let a = {
    name : "JYY",
    height: syb,
    age : undefined,
    msg : {
        addr : "hebei"
    },
    speek : function(){
        console.log(this.name);
    }
}
let b = _.cloneDeep(a);
console.log(a == b);    // false
console.log(a.msg == b.msg);    // false
console.log(a); // { name: 'JYY', height: Symbol(jyy), age: undefined, msg: { addr: 'chengde' },speek: [Function: speek] }
console.log(b); // { name: 'JYY', height: Symbol(jyy), age: undefined, msg: { addr: 'chengde' },speek: [Function: speek] }

原文地址:https://www.cnblogs.com/jyybeam/p/11831298.html