iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
0
Modern Web

從技術文章深入學習 JavaScript系列 第 16

Day 16 [淺拷貝] 淺拷貝與深拷貝

  • 分享至 

  • xImage
  •  

文章選自

作者:浪里行舟

連接:https://juejin.im/post/6844904197595332622

來源:掘金

差別

  • 淺拷貝:

    創建一個新的對象並賦予該對象另一個對象的所有第一層屬性,如果屬性是普通類型則複製新的對象,如果屬性是引用類型則複製內存地址給他。

  • 深拷貝:

    和拷貝的對象一模一樣,而且內存地址完全不同(一個對象改變不同不會影響另一個對象)

聽起來文謅謅的我們直接來看示意圖

淺拷貝分析與示意圖

小故事

​ 假設今天拷貝公司一有一個員工,他叫做淺拷貝,今天他的工作內容很特別,剛好跟他的名子一樣,就是淺拷貝一個對象。這一天他一如既往地在拷貝一個對象foo。

先來看看foo的長相

let foo = {
  bar: 5,
  baz: {
    name: 'Mike',
    age: 15
  }
}

淺拷貝本身是一個很怕麻煩的人,對他來說拷貝任務只需要看起來完成就好,其他沒差啦~~

所以對淺拷貝來說其實 foo 是長這樣

https://ithelp.ithome.com.tw/upload/images/20200930/20124350NIHip5jWXU.png

可以看到,非常的隨便,因此他就開始了他的拷貝任務

工作圖:

https://ithelp.ithome.com.tw/upload/images/20200930/20124350K3Udt4BdEu.png

可以看到其實就是複製第一層地址給他們,相信聰明的各位會發現,如果今天我

更改新foo.baz對象的值(比方說 新foo.baz.age = 20) 會影響到foo.baz

很合理啊!因為內存地址都相同啊

深拷貝分析與示意圖

小故事

繼續淺拷貝的例子,只是今天換成拷貝公司的深拷貝先生來拷貝foo!

​ 深拷貝是一個超級嚴謹的員工,所以他一定要把所有的東西都創新一遍,所以對深拷貝員工來說,他要的foo長這樣

https://ithelp.ithome.com.tw/upload/images/20200930/20124350OZAxEPdt5x.png

哇看起來是真的累人,開始他的工作吧

工作圖

https://ithelp.ithome.com.tw/upload/images/20200930/20124350Q3cmcXG3KO.png

哇簡直可怕的認真,他居然為了對象裡的對象(foo.baz) 開創了新的地址並複製。

可能你會覺得還好,沒有很累人啊。但是他會其實不只第二層,他會把所有的東西都這樣跑一遍意思就是假設

今天 foo.baz.name 不是一個一般類型的話就要繼續重複剛剛的流程下去

如果已經懂得人可以跳到下一個part

比方說今天的 foo.baz.name 長這樣

foo.baz.name = {
  id: 01,
  name: 'Mike'
}

那代表我們還得繼續往下複製下去

https://ithelp.ithome.com.tw/upload/images/20200930/20124350mX6LVXAbjj.png
可見深拷貝是一個多麼認真的魔人

淺拷貝實踐方法

Object.assign()

Object.assign(target, ...sources)

把多個原對象的可枚舉屬性拷貝給目標對象

例子:

let foo = {
  bar: 5,
  baz: {
    name: 'Mike',
    age: 15
  }
}

let copyFoo = Object.assign({}, foo) 

https://ithelp.ithome.com.tw/upload/images/20200930/20124350kzUhZanwds.png

函数库lodash的clone方法

let foo = {
  bar: 5,
  baz: {
    name: 'Mike',
    age: 15
  }
}

const _ = require('loadash');

var copyFoo = _.clone(foo);

展开运算符 ...

ES6新增的,可以實現跟Object.assign一樣效果

let foo = {
  bar: 5,
  baz: {
    name: 'Mike',
    age: 15
  }
}

let copyFoo = {...foo}

// 證明他也是淺拷貝
foo.baz.name = '被改了!'
console.log(copyFoo);

https://ithelp.ithome.com.tw/upload/images/20200930/20124350xyJjOD9Ard.png

Array.prototype.concat()

主要用於數組

let foo = [1, 5, {name: 'Mike'}]

let copyFoo = foo.concat()
foo[2].name = '被改了!'
console.log(copyFoo);

https://ithelp.ithome.com.tw/upload/images/20200930/20124350bscoDIs8dq.png

Array.prototype.slice()

主要用於數組

let foo = [1, 5, {name: 'Mike'}]

let copyFoo = foo.slice()
foo[2].name = '被改了!'
console.log(copyFoo);

https://ithelp.ithome.com.tw/upload/images/20200930/20124350nfw1CuIQUc.png

深拷貝

明天會開一篇來討論~~


上一篇
Day 15 [EventLoop 02] Eventloop不可怕,可怕的是遇上Promise
下一篇
Day 17 [深拷貝] 如何寫出一個驚艷面試官的深拷貝
系列文
從技術文章深入學習 JavaScript29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言