深浅拷贝

前言

转载自:
Java 的深拷贝和浅拷贝_浅拷贝
一篇文章彻底说清JS的深拷贝/浅拷贝

1. 深浅拷贝的来由和区分

除了基本数据类型(元类型)之外,还存在 类的实例实例对象 这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

2. 复合类型深拷贝的最快解

var copyObj = {

    name: 'ziwei',

    arr : [1,2,3]

}

var targetObj = JSON.parse(JSON.stringify(copyObj))

// 此时 copyObj.arr !== targetObj.arr  已经实现了深拷贝 

别着急走,利用window.JSON的方法做深拷贝存在2个缺点:

  1. 如果你的对象里有函数,函数无法被拷贝下来

  2. 无法拷贝copyObj对象原型链上的属性和方法

当然,你明确知道他们的缺点后,如果他的缺点对你的业务需求没有影响,就可以放心使用了,一行原生代码就能搞定。

目前我在开发业务场景中,大多还真可以忽略上面2个缺点。往往需要深拷贝的对象里没有函数,也不需要拷贝它原型链的属性。

3.深拷贝和浅拷贝的实现方式

其实JQ里已经有$.extend()函数,实现就是深拷贝和浅拷贝的功能。有兴趣的小伙伴也可以看看源码。

浅拷贝

浅拷贝比较简单,就是用for in 循环赋值


    function shallowCopy(source, target = {}) {

        var key;

        for (key in source) {

            if (source.hasOwnProperty(key)) {        // 意思就是__proto__上面的属性,我不拷贝

                target[key] = source[key];

            }

        }

        return target;

    }

深拷贝的实现

深拷贝,就是遍历那个被拷贝的对象

判断对象里每一项的数据类型

如果不是对象类型,就直接赋值,如果是对象类型,就再次调用deepCopy,递归的去赋值。

    function deepCopy(source, target = {}) {

        var key;

        for (key in source) {

            if (source.hasOwnProperty(key)) {                        // 意思就是__proto__上面的属性,我不拷贝

                if (typeof(source[key]) === "object") {              // 如果这一项是object类型,就递归调用deepCopy

                    target[key] = Array.isArray(source[key]) ? [] : {};

                    deepCopy(source[key], target[key]);

                } else {                                            // 如果不是object类型,就直接赋值拷贝

                    target[key] = source[key];

                }

            }

        }

        return target;

    }

以上的无论深、浅拷贝,都用了source.hasOwnProperty(key),意思是判断这一项是否是其自有属性,是的话才拷贝,不是就不拷贝。

也就是说proto上面的属性,我不拷贝。这个其实你可以根据业务需求,来决定加上和这个条件

(JQ的$.extend()是会连proto上的属性也拷贝下来的,但是是直接拷贝到对象上,而不是放到之前的proto上)

4.总结与建议

虽然大家可能经常用框架提供的api来实现深拷贝。

这篇文章分享的目的,更多还是希望用一篇文章整理清楚深浅拷贝的含义、递归实现思路,以及小伙伴们如果使用了JSON.parse()这种黑科技,一定要清楚这样写的优缺点。

你可能感兴趣的:(深浅拷贝)