资讯专栏INFORMATION COLUMN

对深拷贝和浅拷贝的全面理解

_DangJin / 2162人阅读

摘要:关于深拷贝和浅拷贝从原理看浅拷贝拷贝一层,对象级别的则拷贝引用深拷贝拷贝多层,每个层级的属性都会拷贝从现象看复制了,被修改后,随变化而变化浅拷贝不变深拷贝深拷贝针对的复杂的类型数据如直接赋值的单层拷贝,如,虽然不受的影响,但是这也不算做

关于深拷贝和浅拷贝

从原理看:

浅拷贝:拷贝一层,对象级别的则拷贝引用

深拷贝:拷贝多层,每个层级的属性都会拷贝

从现象看:
A复制了B,B被修改后,

A随B变化而变化->浅拷贝

A不变->深拷贝

深拷贝针对的s复杂的object类型数据
∴如直接赋值的单层拷贝,如b=a,b虽然不受a的影响,但是这也不算做深拷贝
现象只是作为方便理解的一个参考,真正的判断标准还是要从原理上看

数据类型分为:

基本数据类型(7种):namevalue都存储在栈内存中

引用数据类型:name->栈内存,值->堆内存,栈内存会提供一个引用的地址指向堆内存的值

当b=a进行拷贝时,b复制的是a的引用地址,并不是堆里面的值,所以这便造成了当a发生改变,b也会随之改变的浅拷贝

实现浅拷贝的方法:
一、 直接复制

//基本数据类型
var arr = [1, 2, 3, "4"];

var arr2 = arr;
arr2[1] = "test"; 
console.log(arr); // [1, "test", 3, "4"]
console.log(arr2); // [1, "test", 3, "4"]
//改变其中一个对象的属性值,两个对象都发生了改变 
//obj和obj2两个变量都指向同一个指针,赋值时只是复制了指针地址,它们指向同一个引用,∴当我们改变其中一个的值,另一个变量的值也会随之改变


----------


//对象级
function Clone(obj1){
    var obj2 ={};
    for(var i in obj1)
    {
        obj2[i]=obj1[i];
    }
    return obj2;
}

浅拷贝只是拷贝了一层,除了对象是拷贝引用类型,其他的都是直接将值传递,有自己的内存空间

二、ES6中的Object.assign()方法
该方法可以把任意多个的源对象自身的可枚举属性拷贝给对象,然后返回目标对象

Object.assign(目标对象,任意多个源对象)
var obj1 = {
    a: "hello",
    b: {
        a: "hello",
        b: 21}
};
 
var cloneObj1= Object.assign({}, obj1);
cloneObj1.a = "changed";
cloneObj1.b.a = "changed";
console.log(obj1.a);  //hello
console.log(obj.b.a); // "changed"

如果对象只有一层,这个函数可以作为深拷贝的方法

var obj2 = { a: 10, b: 20, c: 30 };
var cloneObj2 = Object.assign({}, obj2);
cloneObj2.b = 100;
console.log(obj2);
// { a: 10, b: 20, c: 30 } <-- 没有改变,实现了深拷贝
console.log(cloneObj2);
// { a: 10, b: 100, c: 30 }

若想实现深拷贝,就需要在堆中开辟一个内存,用来存放b的值。

方法一、手动复制
将A对象项的属性逐个负责给另一个对象的属性

var ob1 = {a:1,b:2,c:3};
var ob2 = {a:ob1.a,b:ob1.b,c:ob1.c};
ob1.a = 0;
ob2.b = 0;
console.log(ob1);//023
console.log(ob2);//103

这样很麻烦,且本质上不能算作深拷贝,当ob1内嵌套对象c时,ob1和ob2将共享c,当改变c的属性时,ob1ob2将都发生改变

方法二、将对象通过JSON方法转成字符串再转回来
可以实现真正的深拷贝,但是只能用于可以转成JSON格式的对象,function无法转换成JSON,就不能够使用
∴此方法会舍弃对象的构造函数

var ob1 ={c:{a:1,b:2}};
var ob2 =JSON.parse(JSON.stringfy(ob1));
//用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象

方法三、递归拷贝

function deepClone(obj1,obj2){
    var obj = obj2|| {};//如果obj存在则定义为obj2,否则建立空对象
        for(var i in obj1){//遍历原对象
        if(typeof obj1[i] === "object"){//如果当前元素是对象
        
            obj[i] = Array.isArray(obj1[i]) ?[]:{};//判断是数组还是对象 
            deepClone(obj1[i],obj[i]);//利用递归逐层遍历直到最后一层
        }
        else{

            obj[i] = obj1[i];//赋值
        }
        
    }
    return obj;

}

var str = {};
var obj = { a: {a: "Leemo", b: 19980228} };
deepClone(obj, str);
console.log(str.a);

方法四、使用Object.create()方法

var Obj2 = object.create(Obj1);
//实现Obj2深拷贝Obj1

参考文档:
文档1
文档2

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103555.html

相关文章

  • 一篇文章理解JS数据类型、深拷贝和浅拷贝

    摘要:接下来我们进入正片数据类型六种基本数据类型布尔值,和一个表明值的特殊关键字。一种数据类型,它的实例是唯一且不可改变的。在中是没有方法是可以改变布尔值和数字的。参考资料深拷贝浅拷贝 前言 笔者最近整理了一些前端技术文章,如果有兴趣可以参考这里:muwoo blogs。接下来我们进入正片: js 数据类型 六种 基本数据类型: Boolean. 布尔值,true 和 false. nu...

    EddieChan 评论0 收藏0
  • 一篇文章理解JS数据类型、深拷贝和浅拷贝

    摘要:接下来我们进入正片数据类型六种基本数据类型布尔值,和一个表明值的特殊关键字。一种数据类型,它的实例是唯一且不可改变的。在中是没有方法是可以改变布尔值和数字的。参考资料深拷贝浅拷贝 前言 笔者最近整理了一些前端技术文章,如果有兴趣可以参考这里:muwoo blogs。接下来我们进入正片: js 数据类型 六种 基本数据类型: Boolean. 布尔值,true 和 false. nu...

    enda 评论0 收藏0
  • 浅探js深拷贝和浅拷贝

    摘要:接下来就让我们更细致的探究中的深浅拷贝。总结以上对深拷贝和浅拷贝做了简单的介绍,在深拷贝的实现上也只介绍了最简单的实现形式,并未考虑复杂情况以及相应优化,想要对深拷贝有更深入的了解,需要大家花时间去深入研究,或者可以关注我后续文章的动态。 对象和数组的拷贝对我来说一直都是一个比较模糊的概念,一直有点一知半解,但是在实际工作中又偶尔会涉及到,有时候还会一不小心掉坑里,不知道大家有没有同样...

    habren 评论0 收藏0
  • 原生JS 实现复杂对象深拷贝(对象值包含函数)

    摘要:网上有很多方法,比如对象的和的等,但是它们有一个共同的问题就是对简单对象可以实现深拷贝,但是对复杂对象就不行了,比如这样一个对象属性值有函数数组复杂对象等这个时候刚才那几个方法就不行了。 以前对深拷贝和浅拷贝没有太深的印象,后来才知道是因为没掉进去过它的坑里。最近掉坑了才意识到它们的重要性。 闲话少叙,来说说坑:如果我需要保存一个复杂的对象 obj 并把它赋值给 originalObj...

    MkkHou 评论0 收藏0

发表评论

0条评论

_DangJin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<