javascript中的浅拷贝和深拷贝

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);

结果为:

这里写图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值