ES6時代佳镜,你真的會克隆對象嗎(二)

原文:ES6時代启盛,你真的會克隆對象嗎(二)

上一篇,我們從Symbol和是否可枚舉以及屬性描述符的角度分析了ES6下怎么淺拷貝一個對象葛家,發(fā)表在掘金segmentfault上户辞,從評論看,部分人覺著看不懂癞谒,今天底燎,我們用更簡單的方式來聊聊深拷貝的問題

寫在前面

深拷貝的話題好像從來沒有停止過討論,JavaScript并沒有一個可以實現(xiàn)深拷貝的方法弹砚,我們常見的實現(xiàn)方式是遞歸和JSON.parse(JSON.stringify())(聽說底層還是用了遞歸)双仍,然而一般庫函數(shù)也只能處理常見的需求(不常見的需求真的存在嗎?真的需要用深拷貝嗎桌吃?真的不承認是你代碼的問題嗎殊校?)。今天读存,我就仔細为流、認真呕屎,細致(也不是很細致),負責(也不敢太保證)的態(tài)度來研究一下怎么實現(xiàn)一個深拷貝吧敬察,雖然一度放棄秀睛,事實也的確是放棄了,但不把這么多天的付出寫出來怎么對得起那個在這個寒冷的冬天忍住瑟瑟發(fā)抖的在鍵盤上敲擊的我...

常見深拷貝

JSON系列化

JSON.parse(JSON.stringify())的確是一種很簡單易用的方式呢莲祸,可惜的是蹂安,JSON是一個很有原則的男人,他可不會對你言聽計從锐帜。在遇到不安全的JSON值會自動將其忽略田盈,在數(shù)組中則會返回null(以保證單元位置不變)。

不安全的 JSON 值: undefined 缴阎、 function 允瞧、 symbol (ES6+)和包含循環(huán)引用(對象之間相互引用,形成一個無限循環(huán))的 對象 都不符合 JSON 結(jié)構(gòu)標準蛮拔,支持 JSON 的語言無法處理它們

遞歸

上一篇講淺拷貝的時候述暂,我們在開始引入了一個淺拷貝的例子,現(xiàn)在我們把它改成一件簡單的深拷貝建炫。

function deepCopy (obj) {
  if (typeof obj !== 'object') {
    return
  }
  var newObj = obj instanceof Array ? [] : {}
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
    }
  }
  return newObj
}

好像也還不錯畦韭,簡單易懂還能用,一般的場景的確是一種不錯的方法呢肛跌,但是艺配,今天我們來看看不一般的場景。

我們先來挑挑毛惭苌鳌:

  • function類型沒有處理(大概转唉,或許,應(yīng)該是真的沒必要吧西饵,下面我也并不打算討論這貨酝掩,有興趣的去看看callapply眷柔、bind
  • 循環(huán)引用
  • 類型判斷用typeofinstanceof靠譜嗎期虾?(特別注意typeof null的坑)
  • 數(shù)組?[]:{},這么簡單驯嘱?不存在的

循環(huán)引用

上面多處說到了循環(huán)引用的問題镶苞,我們先來看看什么是循環(huán)引用:

var a = {}
a.b = a

是的,就是這么一個反人類的存在鞠评,但是卻是我們不能忽略的一個大問題茂蚓。我們是應(yīng)該返回空呢、undefined呢,還是它的引用聋涨,還是什么呢晾浴?好像沒有標準答案呢,嗯牍白,那就Follow Your Heart吧!

類型判斷

思考一下:

typeof null  // "object"
null instanceof Object  // false

進行類型判斷是無可避免的脊凰,然而我們似乎并沒有什么完美的方式得到我們需要的類型,我們先來看看幾種常用的方式:

  • typeof: 返回一個表達式的數(shù)據(jù)類型的字符串茂腥,返回結(jié)果為js基本的數(shù)據(jù)類型狸涌,包括number,boolean,string,object,undefined,function,symbol
  • instanceof: 判斷一個對象是否為某一數(shù)據(jù)類型,或一個變量是否為一個對象的實例;返回boolean類型最岗。內(nèi)建類型只有通過構(gòu)造器才能用instanceof
  • constructor: 是每一個實例對象都擁有的屬性帕胆,而這個屬性也相當于是一個指針,它指向于創(chuàng)建當前對象的對象
  • Object.prototype.toString.call(obj).slice(8,-1): 返回的是類名

typeof的問題就很明顯了:

typeof null  // "object"
typeof function () {}  // "function"
typeof []  // "object"

instanceof考慮一下多全局對象(多個frame或多個window之間的交互)般渡,在瀏覽器中懒豹,我們的腳本可能需要在多個窗口之間進行交互。多個窗口意味著多個全局環(huán)境诊杆,不同的全局環(huán)境擁有不同的全局對象歼捐,從而擁有不同的內(nèi)置類型構(gòu)造函數(shù)何陆。這可能會引發(fā)一些問題晨汹。比如,表達式 [] instanceof window.frames[0].Array 會返回false贷盲,因為 Array.prototype !== window.frames[0].Array.prototype

constructor屬性得到的僅僅是構(gòu)造函數(shù)淘这,而且是可以被手動更改的,constructor.name只是返回的構(gòu)造函數(shù)的名字巩剖,它并不返回類名铝穷。

Object.prototype.toString.call算是比較公認靠譜的方法了吧,然而佳魔,它同樣有可能被人為仿造曙聂,鴨子類型嘛,但它還是比較安全的方式鞠鲜。

鴨子類型: "如果它走起路來像鴨子宁脊,叫起來也是鴨子,那么它就是鴨子"贤姆。動態(tài)類型的語言傾向于你讓它做什么它就是什么

類型分析

討論鋪墊的內(nèi)容應(yīng)該夠細了吧榆苞,接下來我們看看js的復(fù)雜數(shù)據(jù)類型到底有多復(fù)雜。

我們常見的有:

基本包裝類型(Boolean霞捡、String坐漏、Number)、function、Array赊琳、Date

你常見街夭,但你不一定想的起的:

RegExp,Arguments躏筏,Error莱坎、NodeList

你不一定常見,你也不一定知道的:

Blob寸士、File檐什、FileList、ImageData

ES6:

Map弱卡、Set乃正、WeakMap、WeakSet婶博、ArrayBuffer對象瓮具、TypedArray視圖和DataView視圖、Float32Array凡人、Float64Array名党、Int8Array...

或許列舉的少了不少,但是已經(jīng)夠讓人擔憂深克隆的復(fù)雜程度了挠轴,一一實現(xiàn)他們不是一件簡單的事情传睹,甚至是一件完全沒有必要的事情(當然可以讓你了解更多),推薦幾個很優(yōu)秀的方案供參考:

  • lodash克隆岸晦,lodash花了大量的代碼來實現(xiàn) ES6 引入的大量新的標準對象欧啤。更厲害的是,lodash 針對存在環(huán)的對象的處理也是非常出色的
  • jQuery克隆無法正確深復(fù)制 JSON 對象以外的對象
  • 結(jié)構(gòu)化克隆算法

寫在最后

克隆的部分就寫的差不多了启上,本來想寫點Map邢隧、Set的內(nèi)容的,無賴冈在,并沒有找到合適的地方倒慧,MDN阮一峰的ECMAScript 6 入門都介紹的挺好的包券。

好吧纫谅,就這樣吧,前端界的小學(xué)生兴使,不足之處系宜,還請指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市发魄,隨后出現(xiàn)的幾起案子盹牧,更是在濱河造成了極大的恐慌俩垃,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汰寓,死亡現(xiàn)場離奇詭異口柳,居然都是意外死亡,警方通過查閱死者的電腦和手機有滑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門跃闹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人毛好,你說我怎么就攤上這事望艺。” “怎么了肌访?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵找默,是天一觀的道長。 經(jīng)常有香客問我吼驶,道長惩激,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任蟹演,我火速辦了婚禮风钻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酒请。我一直安慰自己骡技,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布蚌父。 她就那樣靜靜地躺著哮兰,像睡著了一般毛萌。 火紅的嫁衣襯著肌膚如雪苟弛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天阁将,我揣著相機與錄音膏秫,去河邊找鬼。 笑死做盅,一個胖子當著我的面吹牛缤削,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吹榴,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼亭敢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了图筹?” 一聲冷哼從身側(cè)響起帅刀,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤让腹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扣溺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骇窍,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年锥余,在試婚紗的時候發(fā)現(xiàn)自己被綠了腹纳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡驱犹,死狀恐怖嘲恍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雄驹,我是刑警寧澤蛔钙,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站荠医,受9級特大地震影響吁脱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜彬向,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一兼贡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧娃胆,春花似錦遍希、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胁黑,卻和暖如春废封,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丧蘸。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工漂洋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人力喷。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓刽漂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弟孟。 傳聞我的和親對象是個殘疾皇子贝咙,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

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