zoukankan      html  css  js  c++  java
  • javascript中的浅拷贝和深拷贝 分类: JavaScript 2015-05-07 15:29 831人阅读 评论(1) 收藏

    1.js对象浅拷贝

    简单的赋值就是浅拷贝。因为对象和数组在赋值的时候都是引用传递。赋值的时候只是传递一个指针。

    看下面的实例代码:

    var a = [1,2,3];
    var b =a ;
    var test = {name:'xiaohong', age:15};
    var c = test;
    
    console.log(a);
    console.log(b);
    console.log(test);
    console.log('-------------------');
    b[0] =5;
    c.age = 16;
    console.log(a);
    console.log(b);
    console.log(test);
    console.log(c);

    结果如下:
    这里写图片描述

    浅拷贝很容易,但是很多时候我们需要原样的把数组或者对象复制一份,在修改值的时候,不改变初始对象的值。这个时候就需要使用深拷贝。

    2.js对象深拷贝

    因为对象相对较为复杂,所以我们先来看对数组的深拷贝的问题。

    数组的深拷贝

    //深拷贝
    var a = [1,2,3];
    var deepArry = [];
    
    /**
     * @param 被复制数组
     * @param 新数组
     */
    function deepCopy(arry1, arry2){
        for(var i = 0,l= arry1.length;i<l;i++){
            arry2[i] = arry1[i];
        }
    }
    
    deepCopy(a,deepArry);
    console.log(a);
    console.log(deepArry);
    
    deepArry[0] =5;
    console.log(a);
    console.log(deepArry);
    

    运行的结果如下:
    这里写图片描述

    尝试多维数组

    var b = [[1,2,3],4,5];
    deepCopy(b,deepArry);
    console.log(b);
    console.log(deepArry);
    
    deepArry[0][1] =5;
    console.log(b);
    console.log(deepArry);
    

    这里写图片描述

    发现结果不能满足要求,按照上面函数的复制,数组的第二维还是存放着对之前数组的引用。
    对函数进行优化后的代码:

    function deepCopy1(arry1, arry2){
        var tempArry =[];
        for(var i = 0,l= arry1.length;i<l;i++) {
            //判断每一项是不是一个数组
            if (arry1[i] instanceof Array ) {
                deepCopy1(arry1[i], tempArry)
                arry2[i] = tempArry;
            }
            else {
                arry2[i] = arry1[i];
            }
        }
    }
    var b = [[1,2,3],4,5];
    var c = [[1,[2,3]],4,5];
    var d = [[1,2,3],4,[5,6,7]];
    var deepArray = [];
    
    deepCopy1(b, deepArry);
    console.log(deepArry);
    deepArry[0][0] =9;   //修改deepArry的值
    console.log(b);
    console.log(deepArry);
    
    deepArry.length=0;   //初始化deepArray
    deepCopy1(d,deepArry);
    console.log(deepArry);
    
    deepArry.length=0;
    deepCopy1(c,deepArry);
    console.log(c);
    console.log(deepArry);
    deepArry[0][1][0] = 99;
    console.log(c);
    console.log(deepArry);

    运行结果如下:
    这里写图片描述

    对象的深拷贝

    先来看一段代码:

    function Test(){
        this.name='xiaohong',
        this.age=18,
        this.run =function(){
            console.log('run');
        }
    }
    var test = new Test();
    console.log(test.age);
    test.run();
    
    function ChilrTest () {
        this.name = 'xiaogang',
        this.age =15,
        this.sing =function(){
            console.log('sing');
        }
    };
    
    ChilrTest.prototype =  new Test();
    
    var children = new ChilrTest();
    children.sing();
    children.run();
    
    console.log('----childre的属性----') ;
    for (var key in children){
        console.log(key) ;
    }
    

    结果为:

    这里写图片描述

    当我们使用for …in 遍历一个对象的时候他会向上查询原型链上得属性。

    我们可以使用对象的hasOwnProperty属性来过滤掉原型链上得属性

    console.log('----childre的属性----') ;
    for (var key in children){
        if(children.hasOwnProperty(key)) {
            console.log(key);
        }
    }

    结果如下:

    这里写图片描述

    完整的clone一个对象的方法:

    var cloneObject ={};
    for (var key in children){
        if(children.hasOwnProperty(key)) {
            cloneObject[key] = children[key];
        }
    }

    使用js提供的方法深拷贝一维数组

    使用slice函数

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

    结果如下:

    debugger listening on port 57289
    [ 1, 2, 3, 4 ]
    [ 1, 2, 3, 4 ]
    [ 9, 2, 3, 4 ]

    使用concat函数

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

    结果如下:

    debugger listening on port 57320
    [ 1, 2, 3, 4 ]
    [ 1, 2, 3, 4 ]
    [ 9, 2, 3, 4 ]

    jQuery中对数组的clone

    使用jquery进行对象的复制

    jQuery.extend( [ deep ], target , object1 [, objectN... ] )

    请根据前面语法部分所定义的参数名称查找对应的参数。

    参数描述
    deep 可选/Boolean类型指示是否深度合并对象,默认为false。如果该值为true,且多个对象的某个同名属性也都是对象,则该”属性对象”的属性也将进行合并。
    target Object类型目标对象,其他对象的成员属性将被复制到该对象上。 object1 可选/Object类型第一个被合并的对象。
    objectN 可选/Object类型第N个被合并的对象。

    示例代码:

        var a = { k1: 1, k2: 2, k3: 3 };
        var b = {k4:4, k5:5};
        var c ;
        c=$.extend(a);           //将a对象复制到jquery对象上,并赋值给c
        console.log('------------');
        console.log(c === $);    //c对象指向的是$对象,所以结果true
        console.log(a === $);   // false
        console.log('------c------');
        console.log(c.k2);       //相当于$.k2
        console.log('------c------');
        console.log(c);
        //c.k2 = 777;
        console.log('------a------');
        console.log(a);
        console.log('------b------');
        console.log(b);
        console.log('------$------');
        console.log($);
        console.log($.k2);

    结果:
    这里写图片描述
    看下面的一段代码:

        var d = $.extend({}, a)
        console.log(d);
        d.k2 = 3456;
        console.log(d);
        console.log(a);

    结果为:
    这里写图片描述

    可以知道,jquery中extend()不是复制引用,而是创建了新的对象

    注意事项:
    该函数复制的对象属性包括方法在内。此外,还会复制对象继承自原型中的属性(JS内置的对象除外)。
    参数deep的默认值为false,你可以为该参数明确指定true值,但不能明确指定false值。简而言之,第一个参数不能为false值。
    如果参数为null或undefined,则该参数将被忽略。
    如果只为$.extend()指定了一个参数,则意味着参数target被省略。此时,target就是jQuery对象本身。通过这种方式,我们可以为全局对象jQuery添加新的函数。
    如果多个对象具有相同的属性,则后者会覆盖前者的属性值。

    看下面一段代码对数组对象进行拷贝:

        var test = [1,2,34,];
        console.log(test);
        var contest= $.extend([],test);
        console.log(contest);
        contest.push(567);
        console.log(test);
        console.log(contest);

    结果为:

    这里写图片描述

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Vue.js 初尝试
    docker 搭建lnmp开发环境
    【转】【Salesfoece】在 Apex 中得到 sObject 的信息
    【转】【Salesfoece】Approval Process 在 Apex 中的使用
    【转】【Salesfoece】Apex 中 PageReference 的使用
    「codeforces
    「二次剩余」Tonelli
    「loj
    pytest---mock使用(pytest-mock)
    Django---setting文件详解
  • 原文地址:https://www.cnblogs.com/yisuowushinian/p/4715604.html
Copyright © 2011-2022 走看看