js中深浅复制

闲言碎语

  我很早看过相关的大神的博客,但是之前知识掌握不太好,又加上记忆力不太好,所以就忘到十里之外了,今天刷题的时候看到一道问答题,让说说javaScript中的深复制(深度克隆),一刹那有些懵了,就各种搜索理解恶补一下。为了加深记忆和为自己做个笔记的驱动下,写个博客记录一下。

  js中的数据类型,分为两大类:

  基本数据类型:number、string、boolean、null、undefined (使用typeof进行检测判断,返回基本数据类型,但是typeof null =>‘object’)
  引用数据类型:object(使用instanceof 进行检测,返回布尔值)

  两者的区别:

  1、存储方式不同:

  基本数据类型是将变量名和值保存在栈内存中
  引用数据类型是将变量名保存在栈内存中,将值保存在堆内存中,栈内存中有指向堆中(该值)的指针。

  2、赋值方式不同:

  基本数据类型是将变量名和值复制给另一个变量时,新变量将会在栈中开辟一个空间,和之前的变量/值也就无关了(忘恩。。哈哈)
  引用数据类型是将当前变量指向堆内存的指针赋值给了新的变量,此时两个变量共享一个值,所以改变其中一个时另外一个也会发生变化(饮水思源。。嘿嘿)

敲黑板啦

  所谓浅复制就是只是简单的赋值内容,当原内容变化是,新的内容随着变化,看起来很没有主见的样子哈(。。。),深复制就是不管原本的内容如何变化,我的内容就是不变,你变或不变,我的值就是这样不改不变。

浅复制

来个小栗子:

var arr1 = [9,3,[6,5],97,7];
var arr2 = arr1;    //[9,3,[6,5],97,7]
arr1[0] = -1;
console.log(arr2);    //[-1,3,[6,5],97,7]

可以看到arr2完全随着arr1的变化而变化,来个深复制

var color1 = [1,[2,3],3];
var color2 = [];
for(var i  = 0;i < color1.length;i++){
    color2[i] = color1[i]; 
}

console.log(color2);   //[1, [2,3], 3]
color[0] = -1;
color[1][0] = 0;
console.log(color2);     //[1, [0,3], 3]

上面的代码只能浅显的完成一层深复制,想要完全脱离color1的魔爪,还是不能实现。。。js数组中的slice()、concat()、Object.assign()、展开运算符(…)也是达到浅复制效果(请自行实现)。

深复制
  这个呢稍微难理解一点,但是基础程度好的童鞋肯定会一笑而过的。有如下三种方式来实现。

1、通过递归的方式
  在网上搜索你会发现,这中是出现率很高的一种方式,主要原理是对原对象进行递归检查,像上面例子数组中的数组一样,一旦发现子属性中还可以进行遍历,那么,就二话不说的再对其子属性进行遍历,直到只有自身为止(真是榨干榨净啊。。。)

代码实现:

function DeepCopy(obj){
    var res;
    if(Object.prototype.toString.call(obj)=='[object Array]'){    //判断传入参数是不是数组
        res = [];   //是数组的话定义为数组类型
        for(var i = 0;i<obj.length;i++){
            res[i] = DeepCopy(obj[i]);   //对其子元素再进行递归遍历
        }
    }else if(Object.prototype.toString.call(obj) == '[object Object]'){    //判断传入参数是不是对象
        res = {};
        for(var key in obj){
            res[key] = DeepCopy(obj[key]);
        }
    }else{
        return obj;
    }
    return res;
}

使用这个函数再去重新复制 color2 就会有不一样的效果,其中Object.prototype.toString这个方法是干啥的呢??上面也说了使用typeof只能判断基本的类型,如果硬是用这个判断引用类型就会返回 “object”,所以呢可以通过Object.prototype.toString方法,判断某个对象属于哪种内置类型。

2、JSON.stringify与JSON.parse

var arrs = [9,3,[6,5],97,7];

function DeepCopy(obj){
    var _str = JSON.stringify(obj);   //转换为基本类型 
    var news = JSON.parse(_str);  //再次转换,为json格式 再复制
    return news;
}
var ac = DeepCopy(arrs);
console.log(arrs,ac);
arrs[0] = 0;
arrs[2][0] = 0;
console.log(arrs,ac);

result
3、extend
  语法:$.extend( [deep ], target, object1 [, objectN ] )
  deep:指示是否深度合并对象,,为true为深拷贝,为false,则为浅拷贝
  target:Object类型 目标对象,其他对象的成员属性将被附加到该对象上
  object1:可选。 Object类型 第一个被合并的对象

var a1 = [1,2,[3,4],5];
var a2 = $extend(true,[],a1);
console.log(a1,a2);
a1[0] = 0;
a1[2][0] = -1;
console.log(a1,a2);

官方的总结: 希望我写的这篇文章可以帮助你们,站在巨人的肩上可以看的更远,我写的之前也是看了好多关于这方面的知识。。有错或者写的不恰当的地方欢迎指出。

  最后祝大家生活越来越美好,事业越来越顺利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值