js中的浅拷贝和深拷贝

我们都知道,JavaScript中有两种数据类型,基本数据类型和引用数据类型。

对于js中的基本数据类型,如number、string、boolean等,我们都是按值访问,因此浅拷贝是对其值的拷贝;对于引用类型,我们都是按引用访问,即保存在变量对象中的地址。通过该地址去访问堆内存里的实际值。因此,对于相对复杂的object类型的数据,如对象、数组等就存在浅拷贝和深拷贝。

浅拷贝是对对象地址的拷贝,并没有开辟新的内存空间,即复制的结果会是两个对象指向同一个地址,修改其中一个的对象属性,另一个对象属性也会发生改变。

var a = 10;
var b = a;
b = 100;
console.log(a);   //10
console.log(b);   //100
//对象的浅拷贝 
var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = obj1;
obj2.b = 200;
console.log(obj1);  //{a: 10, b: 200, c: 30}
console.log(obj2);  //{a: 10, b: 200, c: 30}

深拷贝则会开辟新的内存空间,两个对象对应不同的地址,修改一个对象的属性,并不会改变另一个对象的属性。如下代码所示:

//深拷贝
var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 200;
console.log(obj1);  // { a: 10, b: 20, c: 30 }
console.log(obj2);  // { a: 10, b: 200, c: 30 }

一.浅拷贝的实现:

我们设想一下如何将一个对象里的属性和方法复制到另一个对象里呢?

var person = { name: 'Mary', age: '20'};
var teacher = {sex: 'man'};
function shallowCopy( obj, obj2 ){
    var obj2 = obj2 || {};
    for( var item in obj ){
        obj2[item] = obj[item]
    }
    return obj2;
}
shallowCopy( person, teacher );
console.log( person );
console.log( teacher );

image.png

但我们如果将代码做如下修改,person对象里面还有一个子对象grade,则在复制时浅拷贝只是将子对象的引用传递给新的对象,因此改变任一个的grade属性都会影响到另一个。
image.png

2.使用Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。如果在这个过程中出现同名的属性(方法),后合并的属性(方法)会覆盖之前的同名属性(方法)。
Object.assign(target,source1,source2,source3);
但是 Object.assign() 进行的也是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

var obj = {a: {b: 1}};
var shallowClone= Object.assign({}, obj);
 
obj2.a.b = 2;
obj.a.b  //2

二.深拷贝的实现

我们需要深拷贝来 解决引用类型的拷贝问题,常见的深拷贝方法有:

1.采用递归的方法去拷贝对象:

ar person = { name: 'Mary', age: '20',grade: {English: 100} };
var teacher = {sex: 'man'};
function deepCopy( obj, obj2 ){
    var obj2 = obj2 || {};
    for( var item in obj ){
        if( typeof obj[item] == 'object'){
        obj2[item] = ( obj[item].constructor === Array )?[]:{};
        deepCopy( obj[item], obj2[item] )
        }else{
            obj2[item] = obj[item];
        }
    }
    return obj2;
}
deepCopy( person, teacher );
teacher.name = 'Tom';
teacher.grade.English = 120;
console.log( person );   
console.log( teacher );
image.png

2.使用JSON方法:

用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。

这种方法虽然简单,但它会抛弃对象的constructor,也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。 并且只能正确处理那些能够被 json 直接表示的数据结构。RegExp对象、function都是无法通过这种方式深拷贝的。

var obj = { grade: { English: 100 }};
var obj2 = JSON.parse( JSON.stringify( obj ));
obj2.grade.English = 110;
console.log( obj.grade.English);  //100
console.log( obj2.grade.English);  //110

3.使用Object.create()方法:
Object.create(prototype, descriptors)
参数说明:

prototype:必需。 要用作原型的对象。 可以为 null。

descriptors“”可选。 包含一个或多个属性描述符的 JavaScript 对象。 “数据属性”是可获取且可设置值的属性。 数据属性描述符包含 value 特性,以及 writable、enumerable 和 configurable 特性。 如果未指定最后三个特性,则它们默认为 false。 只要检索或设置该值,“访问器属性”就会调用用户提供的函数。 访问器属性描述符包含 set 特性和/或 get 特性。

返回值:一个具有指定的内部原型且包含指定的属性(如果有)的新对象。

image.png

个人前端学习笔记均为原创。
首发CSDN:Freya_yyy的博客。欢迎交流和指导。
我是木风,愿你遇见美好!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容