深拷贝与浅拷贝

对于基本类型的数据,深拷贝与浅拷贝都相同,都是开辟一块新的空间,将数组赋值存入。旧值的改变不会影响新值,然鹅对于引用类型的数据就不相同了。

浅拷贝

对于引用类型的数据实行浅拷贝,当旧值发生改变时,新值也会改变,这是因为浅拷贝仅仅只是在栈中新开辟一块空间,将旧值存在栈中的指针复制给新值,新旧值指向的是同一块内存。旧值改变时,新值自然也是改变了的。

var a = [1];
var b = a;
a[0] = 2;
console.log(b); // [2]

实现浅拷贝的方式

Object.assign

展开运算符

只能实现简单数据类型的深拷贝

var a = {name:'ashen'}
var b = {...a}

深拷贝

而在新拷贝中,对于引用类型的拷贝是在堆中新开辟一块空间,将旧的数值复制该这个空间,再在栈中开辟一块空间指向堆中这个地址。新旧值已不再相互影响.

实现深拷贝的几种方式

使用JSON方式

var a = [1, 2, 3];
var b = JSON.parse(JSON.stringify(a));
a[1] = 1;
console.log(b); // [1, 2, 3]

缺点:

  1. 不能实现其中函数的拷贝
  2. 无法拷贝原型链上的属性和方法
  3. 数据层次很深时,会栈溢出

使用递归

function deepClone(obj) {
        var newObj = Array.isArray(obj) ? [] : {};
        for (var key in obj) {
            if (obj[key] instanceof Object) {
                newObj[key] = deepClone(obj[key])
            }else{
                newObj[key] = obj[key]
            }
        }
        return newObj;
    }

    var a = [{name:'ashen', age: 21}, 1]
    var b = deepClone(a);
    console.log(b)

使用数组的forEach实现

function deepClone(obj) {
        var copy = Object.create(Object.getPrototypeOf(obj));
        var propnames = Object.getOwnPropertyNames(obj);
        propnames.forEach(items => {
            let item = Object.getOwnPropertyDescriptor(obj, items);
            Object.defineProperty(copy, items, item)
        })
        return copy;
    }

    var a = [{name:'ashen', age: 21}, 1]
    var b = deepClone(a);
    console.log(b)

注意点:

数组的slice()方法并不能实现深拷贝

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

 

posted @ 2020-04-19 16:17  ashen1999  阅读(96)  评论(0编辑  收藏  举报