实现深拷贝的方法

深拷贝和浅拷贝的概念:

深拷贝拷贝的是对象或者数组内部数据的实体,重新开辟了内存空间存储数据;
浅拷贝拷贝的是引用类型的指针,副本和原数组或对象指向同一个内存;

另一个前提:实现浅复制和深复制的方法区分要看该方法是否对存在于数组或对象的深层的引用类型的值进行真实值的复制,而不是仅对引用进行拷贝,如果这样理解,那么下面的标题的定义应该要做一些修改。

一个方法是是实现了深拷贝还是浅拷贝,要看它是否在拷贝对象或数组时,出现拷贝指针的情况,出现了就是实现了浅拷贝,否则就是实现了深拷贝;

一、一些建立在数组中的各项或对象中的属性值均为基本类型值的前提下的深拷贝的例子

数组

1.concat方法
    var arr1 = [1, 2, 3, 4]
    var arr2 = arr1.concat()//复制当前数组并返回实现深拷贝的副本,arr1独立而不受影响
    console.log(arr2);[1, 2, 3, 4]

    var arr3 = arr1.concat([5, 6, 7])//将数组中的每一项都添加到深拷贝的副本数组中
    console.log(arr3);//[1, 2, 3, 4, 5, 6, 7]
2.slice方法
var arr = [1, 2, 3, 4]

    var arr1 = arr.slice(1)//接收1到2个参数,一个参数时,返回参数指定调用方法数组位置到末尾的值组成的深拷贝副本
    console.log(arr1);//[2, 3, 4]

    var arr2 = arr.slice(0, 1)
    console.log(arr2);//[1]
3.扩展运算符

扩展运算符将一个数组转为用逗号分隔的参数序列

const arr = [1, 2, 3]

    const arr1 = [...arr]
    arr1.push(4)
    console.log(arr1);//[1, 2, 3, 4]
    console.log(arr);//[1, 2, 3]

注意,对于数组项是引用类型的数据,就无法实现深拷贝了。

const arr = [1, 2, 3, [4, 5, 6]]
    const arr1 = [...arr]
    console.log(arr1);
    arr1[3].push(7)
    console.log(arr1);
    console.log(arr);//[1, 2, 3, [4, 5, 6, 7]]更改副本,原数组也被改变

对象

先看一下浅拷贝的例子

var obj = {
      a: 1,
      b: 2
    }

    var obj1 = {}

    obj1 = obj//浅拷贝

    console.log(obj1);//{a: 1, b: 2}
    obj1.c = 3
    console.log(obj);//{a: 1, b: 2, c: 3},更改obj1,obj也被改变
1.Object.assign(目标对象, 源对象),源对象的所有可枚举属性都复制到目标对象上
var obj = {
      a: 1,
      b: 2
    }

    var obj1 = {}

    Object.assign(obj1, obj)
    console.log(obj1);//{a: 1, b: 2}
    obj1.c = 3
    console.log(obj1);//{a: 1, b: 2, c: 3}
    console.log(obj);//{a: 1, b: 2},obj没有被改变,实现了深拷贝
2.JSON
var obj = {
      a: 1,
      b: 2
    }
    
    // 将javascript值转为JSON字符串
    var jsonText = JSON.stringify(obj)
    console.log(jsonText);//{"a":1,"b":2}
    // 把JSON字符串转为javascript值
    var obj1 = JSON.parse(jsonText)
    console.log(obj1);//{a: 1, b: 2}

    // 修改obj1,看原对象值是否被改变
    obj1.c = 3
    console.log(obj1);//{a: 1, b: 2, c: 3}
    console.log(obj);//{a: 1, b: 2},没被改变,实现了深拷贝
3.扩展运算符
 var obj = {
        a: 1,
        b: 2
      }

      var obj1 = {...obj}
      console.log(obj);//{a: 1, b: 2}
      console.log(obj1);//{a: 1, b: 2}
      obj.a = 33
      console.log(obj);//{a: 33, b: 2}
      console.log(obj1);//{a: 1, b: 2}没改变,实现了深拷贝

二、完全实现深拷贝的方法

1.JSON方法

var obj = {
  a: {
    c: 2,
    d: [9, 8, 7]
  },
  b: 4
}
var jsontext = JSON.stringify(obj)
var obj1 =JSON.parse(jsontext) 
console.log(obj);
console.log(obj1);

obj.a.d[0] = 666

console.log(obj);
console.log(obj1);

注意,此处代码放在node环境中运行才会得到期望的结果;
原因为:

并没有什么规范或一组需求指定console.* 方法族如何工作——它们并不是JavaScript 正式
的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript 中的。因此,不同的浏览器和JavaScript 环境可以按照自己的意愿来实现,有时候这会引起混淆。
尤其要提出的是,在某些条件下,某些浏览器的console.log(..) 并不会把传入的内容立即输出。出现这种情况的主要原因是,在许多程序(不只是JavaScript)中,I/O 是非常低速的阻塞部分。所以,(从页面/UI 的角度来说)浏览器在后台异步处理控制台I/O 能够提高性能,这时用户甚至可能根本意识不到其发生。
《你不知道的javascript(中卷)》

2.函数库lodash的_.cloneDeep方法

var _ = require('lodash')

var obj = {
  a: {
    c: 2,
    d: [9, 8, 7]
  },
  b: 4
}

var obj1 = _.cloneDeep(obj)

console.log(obj === obj1);//false

3.递归实现深拷贝

function copy(object) {
  // 判断传入的参数是数组还是对象
  let target = object instanceof Array ? [] : {}
  for (const [k ,v] of Object.entries(object)) {
    target[k] = typeof v == 'object' ? copy(v) : v
  }
  return target
}



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

推荐阅读更多精彩内容