用递归解决对象的深拷贝问题

首先,有关【递归】的知识请参考上一节,链接地址:

【上一篇】:带你刷LeetCode中的递归算法

根据JS中【栈】的知识,我们知道js的基本数据类型是值引用,引用类型是地址引用。在浅拷贝中引用的地址同一个地址引用,修改其中一个对象的属性值,另一个对象也会产生影响;而在深拷贝中,会开辟一个新的内存地址用来存放新对象的值,两个对象对应引用的内存地址不一样 ,修改一个对象并不会对另外一个对象产生影响。更详细的描述请参考关于【栈】的介绍。

【栈】:JS版数据结构-栈

一、浅拷贝

01. 概念

一个新的对象直接拷贝已存在的对象的对象属性的引用,即浅拷贝。

02. 浅拷贝的实现方式

  • 通过for循环复制给另一个对象
var obj = {
    name: 'zhansan',
    msg:{
        txt: '123'
    }
};
var o = {};
for (var k in obj) {
    o[k] = obj[k];
}
console.log(o);  //{name: "zhansan", msg: {txt: 123}} 

  • 通过Object.assign()
var o = {}
Object.assign(o, obj);
console.log(o);// {name: "zhansan", msg: {txt: 123}} 

对于以上两个拷贝,obj中的name是基本数据类型,浅拷贝可以直接赋值得到,msg是个对象,是复杂数据类型,对象会开辟一个新的内存空间存储msg对象,浅拷贝的时候时拷贝的地址是同一个地址。此时改变obj中的txt中的值,o中的txt的值也会改变。

obj.msg.txt = '456'
console.log(obj.msg.txt) // 456
console.log(o.msg.txt) // 456
  • Array.prototype.slice.call()
var arr= [1, { x: 'zhao' }];
var arrNew = Array.prototype.slice.call(arr);
arrNew[1].x = 'zhang';
console.log(arrNew); // [ 1,{ x: 2 } ];
console.log(arr); // [ 1,{ x: 2 } ];

对于数组的拷贝,可以利用数组原型上内置的slice方法。

  • arr.concat()
let arr1 = [1, { a: 2 }];
let arr2 = [3, { b: 4 }];
let arr3 = arr1.concat(arr2);
arr1[1].a = 222;
console.log(arr1);// [ 1, { a: 222 } ]
console.log(arr2);// [ 3, { b: 4 } ]
console.log(arr3);// [ 1,{ a: 222 }, 3,{ b: 4 } ]

数组合并也是一个浅拷贝。

二、深拷贝

01. 概念

深拷贝会另外拷贝一份一个一模一样的对象,从堆内存中开辟一个新的区域存放新对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
简单说:深拷贝把存放对象的空间地址,再复制一份给新对象,这样两个对象直接互不干扰。

02. 深拷贝的实现方式

基于基本数据类型直接循环复制,对于复杂数据类型再次运用for循环操作,每一级都要循环拷贝。我们可以使用递归,对于遇到对象再次调用for循环即可。

function deepCopy(newobj, oldobj) {
    for (var k in oldobj) {
        var item = oldobj[k];
        if (item instanceof Array) {
            newobj[k] = [];
            deepCopy(newobj[k], item)
        } else if (item instanceof Object) {
            newobj[k] = {};
            deepCopy(newobj[k], item)
        } else {
            newobj[k] = item;
        }
    }
}
deepCopy(o, obj);
obj.msg.txt = 456
console.log(obj.msg.txt) //456
console.log(o.msg.txt) // 123

下一篇:JS中的算法.排序

推荐阅读:

1. JS. 类

2. JS. 构造函数

3. JS中对象原型proto及原型链

4. JS. 构造函数的原型 prototype

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

推荐阅读更多精彩内容