JS面試題:深淺拷貝簡析/手寫深拷貝函數(shù)

深淺拷貝

對象類型在賦值的過程中實(shí)際上是復(fù)制了地址屎飘,從而導(dǎo)致了其中一方被改變其他也都被改變的情況妥曲,在開發(fā)中我們通常不希望出現(xiàn)這樣的問題,這里可以使用淺拷貝來解決這個情況钦购。

let a = { name: "Jack" }
let b = a
a.name = "Rose"
console.log(b.name) // Rose

什么是淺拷貝檐盟?如何實(shí)現(xiàn)淺拷貝?

首先我們可以通過Object.assign來實(shí)現(xiàn)淺拷貝肮雨,該函數(shù)只會拷貝所有的屬性值到新的對象中遵堵,如果屬性值是對象的話箱玷,拷貝的是地址怨规,即為淺拷貝而不是深拷貝。
以下為Object.assign淺拷貝的簡單實(shí)現(xiàn):

let a = { name: "Jack" }
let b = Object.assign({}, a)
a.name = "Rose"
console.log(b.name) // Jack

還可以通過展開運(yùn)算符...來實(shí)現(xiàn)淺拷貝:

let a = { name: "Jack" }
let b = { ...a }
a.name = "Rose"
console.log(b.name) // Jack

但是锡足,淺拷貝只解決了第一層的問題波丰,如果對象下還有對象的話,那么又回到最開始的問題了舶得,第二層的對象拷貝過來的只是地址掰烟,兩者享有相同的地址,這時(shí)就需要用到深拷貝了沐批。

什么是深拷貝纫骑?如何實(shí)現(xiàn)深拷貝?

我們通常使用JSON.parse(JSON.stringify(object))來解決:

let a = {
    name: "Jack",
    parents: { mother: "Mom" }
}
let b = JSON.parse(JSON.stringify(a))
a.parents.mother = "Mama"
console.log(b.parents.mother) // Mom

但是該方法具有以下局限性:

  • 會忽略undefined
  • 會忽略symbol
  • 不能序列化函數(shù)
  • 不能解決循環(huán)引用的對象

遇到函數(shù)九孩、undefined和symbol時(shí)先馆,會直接忽略掉他們,該對象不能正常的序列化躺彬,此時(shí)我們需要實(shí)現(xiàn)一個更為完善的深拷貝煤墙。

手寫一個深拷貝

function deepClone(obj) {
    // 首先刨除數(shù)組和對象外的所有類型,包括null
    if (typeof obj !== 'object' || obj == null) {
        return obj
    }

    // 創(chuàng)建一個result變量宪拥,存入深拷貝的結(jié)果
    let result

    // 判斷obj是數(shù)組還是對象仿野,并相應(yīng)初始化
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }

    // 采用遞歸的思想,將每一層嵌套deepClone修改
    for (let key in obj) {
        // 在拷貝時(shí)我們只拷貝對象的原有屬性她君,而不拷貝其原型的屬性
        if (obj.hasOwnProperty(key)) {
            result[key] = deepClone(obj[key])
        }
    }

    // 最后返回深拷貝的結(jié)果
    return result
}

小結(jié):以上深拷貝的方法依然只是較為簡易的脚作,要想實(shí)現(xiàn)一個比較完美的深拷貝其實(shí)是很困難的,需要我們考慮很多種邊界情況缔刹,比如原型鏈如何處理球涛、DOM如何處理等魄梯。該deepClone函數(shù)就有兩個較為明顯的問題,一是沒有解決對象的循環(huán)引用的問題(參考方案:用弱映射做一個哈希表宾符,存儲原對象酿秸,若緩存命中,則過濾本次拷貝魏烫,直接使用記憶化數(shù)據(jù)辣苏,否則惰性拷貝。一般不是為了解決IE的兼容性問題哄褒,都沒有問題稀蟋,考慮兼容性則按需墊片。生產(chǎn)環(huán)境其實(shí)還需要考慮其它類型的拷貝呐赡,一般直接使用輔助工具庫退客。總而言之链嘀,按需拷貝)萌狂;二是無法實(shí)現(xiàn)函數(shù)的拷貝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怀泊,一起剝皮案震驚了整個濱河市茫藏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霹琼,老刑警劉巖务傲,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異枣申,居然都是意外死亡售葡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門忠藤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挟伙,“玉大人,你說我怎么就攤上這事熄驼∠窈” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵瓜贾,是天一觀的道長诺祸。 經(jīng)常有香客問我,道長祭芦,這世上最難降的妖魔是什么筷笨? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上胃夏,老公的妹妹穿的比我還像新娘轴或。我一直安慰自己,他們只是感情好仰禀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布照雁。 她就那樣靜靜地躺著,像睡著了一般答恶。 火紅的嫁衣襯著肌膚如雪饺蚊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天悬嗓,我揣著相機(jī)與錄音污呼,去河邊找鬼。 笑死包竹,一個胖子當(dāng)著我的面吹牛燕酷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播周瞎,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼苗缩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了堰氓?” 一聲冷哼從身側(cè)響起挤渐,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎双絮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體得问,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡囤攀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宫纬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焚挠。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖漓骚,靈堂內(nèi)的尸體忽然破棺而出蝌衔,到底是詐尸還是另有隱情,我是刑警寧澤蝌蹂,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布噩斟,位于F島的核電站,受9級特大地震影響孤个,放射性物質(zhì)發(fā)生泄漏剃允。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斥废。 院中可真熱鬧椒楣,春花似錦、人聲如沸牡肉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽统锤。三九已至凤壁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跪另,已是汗流浹背拧抖。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留免绿,地道東北人唧席。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像嘲驾,于是被迫代替她去往敵國和親淌哟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容