賦值,淺拷貝和深拷貝

賦值

賦值是將某一數(shù)值或?qū)ο筚x給某個變量的過程璃谨,分為下面 2 部分

  • 基本數(shù)據(jù)類型:賦值沙庐,賦值之后兩個變量互不影響
  • 引用數(shù)據(jù)類型:賦址,兩個變量具有相同的引用佳吞,指向同一個對象拱雏,相互之間有影響
    對基本類型進(jìn)行賦值操作,兩個變量互不影響底扳。
let a = "muyiy";
let b = a;
console.log(b);
// muyiy

a = "change";
console.log(a);
// change
console.log(b);
// muyiy
為什么要使用淺拷貝和深拷貝

對引用類型進(jìn)行賦址操作铸抑,兩個變量指向同一個對象,改變變量 a 之后會影響變量 b衷模,哪怕改變的只是對象 a 中的基本類型數(shù)據(jù)鹊汛。

let a = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    }
}
let b = a;
console.log(b);
// {
//  name: "muyiy",
//  book: {title: "You Don't Know JS", price: "45"}
// } 

a.name = "change";
a.book.price = "55";
console.log(a);
// {
//  name: "change",
//  book: {title: "You Don't Know JS", price: "55"}
// } 

console.log(b);
// {
//  name: "change",
//  book: {title: "You Don't Know JS", price: "55"}
// } 

通常在開發(fā)中并不希望改變變量 a 之后會影響到變量 b,這時就需要用到淺拷貝深拷貝阱冶。

淺拷貝

什么是淺拷貝

創(chuàng)建一個新對象刁憋,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性是基本類型木蹬,拷貝的就是基本類型的值至耻,如果屬性是引用類型,拷貝的就是內(nèi)存地址 镊叁,所以如果其中一個對象改變了這個地址尘颓,就會影響到另一個對象。


image.png

上圖中晦譬,SourceObject 是原對象疤苹,其中包含基本類型屬性 field1 和引用類型屬性 refObj。淺拷貝之后基本類型數(shù)據(jù) field2 和 filed1 是不同屬性蛔添,互不影響痰催。但引用類型 refObj 仍然是同一個,改變之后會對另一個對象產(chǎn)生影響迎瞧。

簡單來說可以理解為淺拷貝只解決了第一層的問題夸溶,拷貝第一層的基本類型值,以及第一層的引用類型地址凶硅。

淺拷貝使用場景

1.Object.assign()
Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象復(fù)制到目標(biāo)對象缝裁。它將返回目標(biāo)對象。

let a = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    }
}
let b = Object.assign({}, a);
console.log(b);
// {
//  name: "muyiy",
//  book: {title: "You Don't Know JS", price: "45"}
// } 

a.name = "change";
a.book.price = "55";
console.log(a);
// {
//  name: "change",
//  book: {title: "You Don't Know JS", price: "55"}
// } 

console.log(b);
// {
//  name: "muyiy",
//  book: {title: "You Don't Know JS", price: "55"}
// } 

上面代碼改變對象 a 之后,對象 b 的基本屬性保持不變捷绑。但是當(dāng)改變對象 a 中的對象 book 時韩脑,對象 b 相應(yīng)的位置也發(fā)生了變化。

2.Array.prototype.slice()
slice() 方法返回一個新的數(shù)組對象粹污,這一對象是一個由 begin和 end(不包括end)決定的原數(shù)組的淺拷貝段多。原始數(shù)組不會被改變。

// 木易楊
let a = [0, "1", [2, 3]];
let b = a.slice(1);
console.log(b);
// ["1", [2, 3]]

a[1] = "99";
a[2][0] = 4;
console.log(a);
// [0, "99", [4, 3]]

console.log(b);
//  ["1", [4, 3]]

可以看出壮吩,改變 a[1] 之后 b[0] 的值并沒有發(fā)生變化进苍,但改變 a[2][0] 之后,相應(yīng)的 b[1][0] 的值也發(fā)生變化鸭叙。說明 slice() 方法是淺拷貝觉啊,相應(yīng)的還有concat等,在工作中面對復(fù)雜數(shù)組結(jié)構(gòu)要額外注意沈贝。

深拷貝

什么是深拷貝

淺拷貝只解決了第一層的問題杠人,如果接下去的值中還有對象的話,那么就又回到剛開始的話題了宋下,兩者享有相同的引用嗡善。要解決這個問題,我們需要引入深拷貝杨凑。深拷貝會拷貝所有的屬性滤奈,并拷貝屬性指向的動態(tài)分配的內(nèi)存。當(dāng)對象和它所引用的對象一起拷貝時即發(fā)生深拷貝撩满。深拷貝相比于淺拷貝速度較慢并且花銷較大蜒程。拷貝前后兩個對象互不影響伺帘。


image.png
深拷貝使用場景

1.JSON.parse(JSON.stringify(object))

let a = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    }
}
let b = JSON.parse(JSON.stringify(a));
console.log(b);
// {
//  name: "muyiy",
//  book: {title: "You Don't Know JS", price: "45"}
// } 

a.name = "change";
a.book.price = "55";
console.log(a);
// {
//  name: "change",
//  book: {title: "You Don't Know JS", price: "55"}
// } 

console.log(b);
// {
//  name: "muyiy",
//  book: {title: "You Don't Know JS", price: "45"}
// } 

但是該方法有以下幾個問題昭躺。

  • 會忽略 undefined
  • 會忽略 symbol
  • 不能序列化函數(shù)
  • 不能解決循環(huán)引用的對象
  • 不能正確處理new Date()
  • 不能處理正則
let obj = {
    name: 'muyiy',
    a: undefined,
    b: Symbol('muyiy'),
    c: function() {}
}
console.log(obj);
// {
//  name: "muyiy", 
//  a: undefined, 
//  b: Symbol(muyiy), 
//  c: ? ()
// }

let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "muyiy"}
  • 循環(huán)引用情況下,會報錯
let obj = {
    a: 1,
    b: {
        c: 2,
        d: 3
    }
}
obj.a = obj.b;
obj.b.c = obj.a;

let b = JSON.parse(JSON.stringify(obj));
// Uncaught TypeError: Converting circular structure to JSON
  • new Date 情況下伪嫁,轉(zhuǎn)換結(jié)果不正確
new Date();
// Mon Dec 24 2018 10:59:14 GMT+0800 (China Standard Time)

JSON.stringify(new Date());
// ""2018-12-24T02:59:25.776Z""

JSON.parse(JSON.stringify(new Date()));
// "2018-12-24T02:59:41.523Z"

解決方法轉(zhuǎn)成字符串或者時間戳就好了领炫。

let date = (new Date()).valueOf();
// 1545620645915

JSON.stringify(date);
// "1545620673267"

JSON.parse(JSON.stringify(date));
// 1545620658688
  • 正則情況下
let obj = {
    name: "muyiy",
    a: /'123'/
}
console.log(obj);
// {name: "muyiy", a: /'123'/}

let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "muyiy", a: {}}

總結(jié)

image.png

參考文章

https://github.com/yygmind/blog/issues/25

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市张咳,隨后出現(xiàn)的幾起案子帝洪,更是在濱河造成了極大的恐慌,老刑警劉巖脚猾,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葱峡,死亡現(xiàn)場離奇詭異,居然都是意外死亡龙助,警方通過查閱死者的電腦和手機(jī)砰奕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人军援,你說我怎么就攤上這事仅淑。” “怎么了胸哥?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵涯竟,是天一觀的道長。 經(jīng)常有香客問我烘嘱,道長昆禽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任蝇庭,我火速辦了婚禮,結(jié)果婚禮上捡硅,老公的妹妹穿的比我還像新娘哮内。我一直安慰自己,他們只是感情好壮韭,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布北发。 她就那樣靜靜地躺著,像睡著了一般喷屋。 火紅的嫁衣襯著肌膚如雪琳拨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天屯曹,我揣著相機(jī)與錄音狱庇,去河邊找鬼。 笑死恶耽,一個胖子當(dāng)著我的面吹牛密任,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偷俭,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼浪讳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涌萤?” 一聲冷哼從身側(cè)響起淹遵,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎负溪,沒想到半個月后透揣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笙以,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年淌实,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡拆祈,死狀恐怖恨闪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情放坏,我是刑警寧澤咙咽,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站淤年,受9級特大地震影響钧敞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麸粮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一溉苛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧弄诲,春花似錦愚战、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梗摇,卻和暖如春拓哟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背伶授。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工断序, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谎砾。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓逢倍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親景图。 傳聞我的和親對象是個殘疾皇子较雕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351