作者:?緝熙Soyaine
簡(jiǎn)介:JavaScript30 是 Wes Bos 推出的一個(gè) 30 天挑戰(zhàn)。項(xiàng)目免費(fèi)提供了 30 個(gè)視頻教程、30 個(gè)挑戰(zhàn)的起始文檔和 30 個(gè)挑戰(zhàn)解決方案源代碼。目的是幫助人們用純 JavaScript 來(lái)寫東西,不借助框架和庫(kù),也不使用編譯器和引用?,F(xiàn)在你看到的是這系列指南的第 14 篇。完整指南在 GitHub,喜歡請(qǐng) Star 哦?(?*)
創(chuàng)建時(shí)間:2017-07-19
最后更新:2017-07-21
實(shí)現(xiàn)效果
這個(gè)部分主要是幫助你通過(guò)不同的語(yǔ)句來(lái)感受在 JavaScript 中對(duì)不同類型數(shù)據(jù)的引用(Reference)和復(fù)制(Copy)的區(qū)別。由于操作在 Console 中進(jìn)行,所以請(qǐng)直接運(yùn)行頁(yè)面后打開(kāi) Console,邊編輯代碼,邊查看結(jié)果。
過(guò)程指南
-
首先從 String、Number、Boolean 類型的值開(kāi)始。
let age = 100; let age2 = age; console.log(age, age2); // 100 100 age = 200; console.log(age, age2); // 200 100先聲明了一個(gè) Number 型的變量
age,并將此變量賦值給另一個(gè)變量age2,這時(shí)兩個(gè)變量的值都是 100。
然后賦給age新的值,可見(jiàn)對(duì)age的修改并不會(huì)對(duì)age2造成影響。 -
那對(duì)于數(shù)組來(lái)說(shuō),情況是否一樣呢?下面我們來(lái)看看數(shù)組。
const players = ['Wes', 'Sarah', 'Ryan', 'Poppy']; const team = players; console.log(players, team);延續(xù)上面的思路,先聲明一個(gè)數(shù)組
players,并將其賦值給team。試想一下,如果需要修改team中的值,我們可以如何操作?或許可以這樣?team[3] = 'Lux';來(lái)看看發(fā)生了什么。
console.log(players, team); // ["Wes", "Sarah", "Ryan", "Lux"] ["Wes", "Sarah", "Ryan", "Lux"]WOW 原數(shù)組
plaryers也被修改了。為什么會(huì)這樣?因?yàn)?team只是這個(gè)數(shù)組的引用,并不是它的復(fù)制。team和players這兩個(gè)變量指向的是同一個(gè)數(shù)組。
所以如何解決這個(gè)問(wèn)題?接下來(lái)我們開(kāi)始真正的復(fù)制吧!-
由于運(yùn)行
slice得到的結(jié)果是一個(gè)對(duì)原數(shù)組的淺拷貝,原數(shù)組不會(huì)被修改。所以如果修改這兩個(gè)數(shù)組中任意 一個(gè),另一個(gè)都不會(huì)受到影響。const team2 = players.slice(); team2[3] = 'Lux2'; console.log(players, team2); -
concat()方法是用來(lái)合并數(shù)組的,它也不會(huì)更改原有的數(shù)組,而是返回一個(gè)新數(shù)組,所以可以將players數(shù)組與一個(gè)空數(shù)組合并,得到的結(jié)果就符合預(yù)期了。const team3 = [].concat(players); team3[3] = 'Lux3'; console.log(players, team3); -
方法三 ES6 擴(kuò)展語(yǔ)法
擴(kuò)展語(yǔ)法可以像擴(kuò)展參數(shù)列表一樣來(lái)擴(kuò)展數(shù)組,效果與上述方法類似,但比較簡(jiǎn)潔。
const team4 = [...players]; team4[3] = 'Lux4'; console.log(players, team4); -
方法四
Array.from()此外使用 Array 創(chuàng)建新的數(shù)組實(shí)例的方法也是可行的。
const team5 = Array.from(players); team5[3] = 'Lux5'; console.log(players, team5);
除此之外,還可以用
push這樣的方法。數(shù)組部分已經(jīng)介紹完畢,下面我們進(jìn)入 Object 類型數(shù)據(jù)的試驗(yàn)吧~ -
-
對(duì)于 Object 數(shù)據(jù),我們用一個(gè)
person對(duì)象來(lái)試試。先聲明對(duì)象:
const person = { name: 'Wes Bos', age: 80 };然后思考一下如何可以取得它的復(fù)制,試試想當(dāng)然的做法:
const captain = person; captain.number = 99; console.log(person, captain); // Object {name: "Wes Bos", age: 80, number: 99} // Object {name: "Wes Bos", age: 80, number: 99}這樣好像行不通,
person的值也被更改了,那該如何才能真正復(fù)制呢?-
方法一
Object.assign()使用
Object.assign(target, ...sources)時(shí),后來(lái)的源對(duì)象的屬性值,將會(huì)覆蓋它之前的對(duì)象的屬性。所以可以先復(fù)制person之后,再賦給屬性新的值。const cap2 = Object.assign({}, person, { number: 99, age: 12 }); console.log(cap2); // Object {name: "Wes Bos", age: 12, number: 99} -
方法二 JSON 轉(zhuǎn)換
利用 JSON 可以先將對(duì)象轉(zhuǎn)成字符串的格式,然后再把它轉(zhuǎn)成 JSON,從而實(shí)現(xiàn)復(fù)制。
const wes = { name: 'Wes', age: 100, social: { twitter: '@wesbos', facebook: 'wesbos.developer' } }; const dev = Object.assign({}, wes); const dev2 = JSON.parse(JSON.stringify(wes)); console.log(wes); console.log(dev); console.log(dev2);
-
最后需要注意的是:在前面的例子里面,我們用的數(shù)組和對(duì)象都只是一層嵌套,Lodash 有一個(gè)深度復(fù)制的方法,但你使用之前需要多考慮一下。
OVER(^o^)/