zoukankan      html  css  js  c++  java
  • javascript深拷贝和浅拷贝

    在JavaScript中,存在着这样的两种拷贝方式。分别是:深拷贝和浅拷贝,这两种拷贝在实际中非常的常见,如果读者是一个阅读源码的爱好者,相信多多少少对深拷贝和浅拷贝有所了解。

    一、浅拷贝

    浅拷贝在现实中最常见的表现在赋值上面,例如

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>测试</title>
    </head>
    <body>
        <script type="text/javascript">
            //第一个数组
            var test=["1","2","3"];
            //第二个数组
            var test2=[];
            test2=test;
            test2[1]="two";
            console.log(test);//运行的结果是["1","two","3"]
        </script>
    </body>
    </html>

    从上面的例子,我们修改test2数组的值,最后打印test数组,发现test也跟着改变了。

    其实这个就是一个最浅的浅拷贝,相当于test2=test这个阶段是在将test数组中的存储地址索引赋值给test2数组,所以两个数组都是指向同一块存储地址中去。

    除了这种方法可以实现浅拷贝,还有使用slice和concat进行浅拷贝

    例如:我们测试一次slice这个方法

    <script type="text/javascript">
        var arr=["demo1","demo2","demo3"];
        var arr2=arr.slice(0);
        arr2[1]="test";
        console.log(arr);//["demo1","demo2","demo3"]
        console.log(arr2);//["demo1","test","demo3"]
    </script>

    从上面的例子我们可以看出,使用slice方法对数组进行了深度拷贝,

    同理,concat的用法如下

    <script type="text/javascript">
        var arr=["demo1","demo2","demo3"];
        var arr2=arr.concat();
        arr2[1]="test";
        console.log(arr);//["demo1","demo2","demo3"]
        console.log(arr2);//["demo1","test","demo3"]
    </script>

    为何这样已经算得上是深拷贝的东西,我又称之为浅拷贝呢?

    其实使用slice和concat这两个方法部分都是不可以拷贝如下的这种情况的:

    运行如下的代码:

    <script type="text/javascript">
        var arr = [1,3,[4,7,65,9]];
        var arr1=arr.slice(0);
        arr1[2][2]=2;
        console.log(arr1[2][2]);
        console.log(arr);
    </script>

    或者是如下的这一段代码: 

    <script type="text/javascript">
        var arr = [1,3,[4,7,65,9]];
        var arr1=arr.concat();
        arr1[2][2]=2;
        console.log(arr1[2][2]);
        console.log(arr);
    </script>

    我们都可以看到,我们拷贝了arr的值,然后同时修改arr1的值,我们可以看到arr也被修改了。

    所以对于Slice和concat这两个方法来说都是浅拷贝,只能拷贝数组中的第一层

    另外除了可以对数组进行浅拷贝,同样的我们也可以对JSON数据进行浅拷贝

    assign这个方法可以对object对象进行复制,但是这种拷贝是浅拷贝跟直接赋值却又是不一样的。

    assign其中接受两个参数,第一个参数指代的是拷贝之后需要修改的内容,第一个参数指代的是要拷贝的内容

    <script type="text/javascript">
        var obj = { a: {a: "hello", b: 21} }; 
        var initalObj = Object.assign({b:{"test":1111}}, obj); 
        initalObj.a.a = "changed"; 
        console.log(obj);
        console.log(initalObj);
        console.log(obj.a.a); // "changed"
        console.log(obj===initalObj);//false
    </script>

    运行上面的代码可以看到,obj 里面的值也被修改了

    二、深拷贝

     最简单的深拷贝就莫过于使用JSON对象提供的方法。

     我们先来个例子测试一下:

    <script type="text/javascript">
        var json={
            "a":"test",
            "b":"test1"
        };
        var b=JSON.parse(JSON.stringify(json));
        b.a="demo";
        console.log(json);//{"a":"test","b":"test1"}
    </script>

    我们修改了b中的值,但是打印json对象发现没有被修改到,这个已经就是深度拷贝的。

    但是转换后的原来的值类型会出现丢失,也就是最后的类型一定是Object类型。

    说道深拷贝,就不能不提Jquery中中的extend方法,这个方法如果是有学习制作插件的同学应该都会知道,这个方法用于生成一个全新的JSON对象值。

    其实这个本身就是一种深拷贝的应用,具体的代码如下:

        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
        <script type="text/javascript">
            var arr=["test",["demo1","demo2"]];
            var arr1=$.extend({},arr);
            arr[1][0]=1;
            console.log(arr1);
        </script>

    上面的代码运行的时候,我们可以看到即使是数组也是同样可以深度拷贝的。

    具体的解释是:因为上面我们已经说过数组类型其实就是一种object类型,那么extend方法是用来对object类型进行深拷贝的,那么也就是满足了数组的这一种情况,当然博主是没有去看源码的,所以如果解释与源码有出入,望请指正。

    说一说最后的一种实现深拷贝的方法吧,也就是遍历原对象,并将原对象赋值给生成后的对象,具体的方式详见:

    http://blog.csdn.net/hj7jay/article/details/51986486

  • 相关阅读:
    Android——继续深造——从安装Android Studio 2.0开始(详)
    PHP——安装wampserver丢失MSVCR110.dll
    Marza Gift for GDC 2016
    Retrieve OpenGL Context from Qt 5.5 on OSX
    Space Time Varying Color Palette
    Screen Space Depth Varying Glow based on Heat Diffusion
    Visualization of Detail Point Set by Local Algebraic Sphere Fitting
    Glass Dragon
    Jump Flood Algorithms for Centroidal Voronoi Tessellation
    京都之行
  • 原文地址:https://www.cnblogs.com/st-leslie/p/7128765.html
Copyright © 2011-2022 走看看