關(guān)于JSON.parse(JSON.stringify(obj))實(shí)現(xiàn)深拷貝應(yīng)該注意的坑

JSON.parse(JSON.stringify(obj))我們一般用來深拷貝图贸,其過程說白了 就是利用JSON.stringify 將js對象序列化(JSON字符串),再使用JSON.parse來反序列化(還原)js對象霍殴;序列化的作用是存儲(對象本身存儲的只是一個地址映射,如果斷電,對象將不復(fù)存在纵顾,因此需將對象的內(nèi)容轉(zhuǎn)換成字符串的形式再保存在磁盤上 )和傳輸(例如 如果請求的Content-Type是?application/x-www-form-urlencoded洁奈,則前端這邊需要使用qs.stringify(data)來序列化參數(shù)再傳給后端间唉,否則后端接受不到; ps:?Content-Type?為?application/json;charset=UTF-8或者?multipart/form-data?則可以不需要 )利术;我們在使用?JSON.parse(JSON.stringify(xxx))時應(yīng)該注意一下幾點(diǎn):

1呈野、如果obj里面有時間對象,則JSON.stringify后再JSON.parse的結(jié)果印叁,時間將只是字符串的形式被冒。而不是時間對象;

vartest={name:'a',date:[newDate(1536627600000),newDate(1540047600000)],};letb;b=JSON.parse(JSON.stringify(test))

test 結(jié)果.png

b的結(jié)果

測試b和test類型

2轮蜕、如果obj里有RegExp姆打、Error對象,則序列化的結(jié)果將只得到空對象肠虽;

consttest={name:'a',date:newRegExp('\\w+'),};// debuggerconstcopyed=JSON.parse(JSON.stringify(test));test.name='test'console.error('ddd',test,copyed)

image.png

3幔戏、如果obj里有函數(shù),undefined税课,則序列化的結(jié)果會把函數(shù)或 undefined丟失闲延;

consttest={name:'a',date:functionhehe(){console.log('fff')},};// debuggerconstcopyed=JSON.parse(JSON.stringify(test));test.name='test'console.error('ddd',test,copyed)

image.png

image.png

4、如果obj里有NaN韩玩、Infinity和-Infinity垒玲,則序列化的結(jié)果會變成null

image.png

5、JSON.stringify()只能序列化對象的可枚舉的自有屬性找颓,例如 如果obj中的對象是有構(gòu)造函數(shù)生成的合愈, 則使用JSON.parse(JSON.stringify(obj))深拷貝后,會丟棄對象的constructor击狮;

functionPerson(name){this.name=name;console.log(name)}constliai=newPerson('liai');consttest={name:'a',date:liai,};// debuggerconstcopyed=JSON.parse(JSON.stringify(test));test.name='test'console.error('ddd',test,copyed)

image.png

6佛析、如果對象中存在循環(huán)引用的情況也無法正確實(shí)現(xiàn)深拷貝;

以上彪蓬,如果拷貝的對象不涉及上面講的情況寸莫,可以使用JSON.parse(JSON.stringify(obj))實(shí)現(xiàn)深拷貝,但是涉及到上面的情況(除循環(huán)引用的情況外)档冬,可以考慮使用如下方法實(shí)現(xiàn)深拷貝:

functiondeepClone(data){consttype=this.judgeType(data);letobj;if(type==='array'){obj=[];}elseif(type==='object'){obj={};}else{// 不再具有下一層次returndata;}if(type==='array'){// eslint-disable-next-linefor(leti=0,len=data.length;i<len;i++){obj.push(this.deepClone(data[i]));}}elseif(type==='object'){// 對原型上的方法也拷貝了....// eslint-disable-next-linefor(constkeyindata){obj[key]=this.deepClone(data[key]);}}returnobj;}functionjudgeType(obj){// tostring會返回對應(yīng)不同的標(biāo)簽的構(gòu)造函數(shù)consttoString=Object.prototype.toString;constmap={'[object Boolean]':'boolean','[object Number]':'number','[object String]':'string','[object Function]':'function','[object Array]':'array','[object Date]':'date','[object RegExp]':'regExp','[object Undefined]':'undefined','[object Null]':'null','[object Object]':'object',};if(objinstanceofElement){return'element';}returnmap[toString.call(obj)];}

如果被拷貝中沒有對時間膘茎、正則要求兼容桃纯,可以采用如下方法

functiondeepClone(obj){if(obj&&typeofobj==='object'){varnewObj=Array.isArray(obj)?[]:{};for(varkeyinobj){if(obj.hasOwnProperty(key)){if(obj[key]&&typeofobj[key]==='object'){newObj[key]=deepClone(obj[key])}else{newObj[key]=obj[key]}}}}else{console.error('輸入?yún)?shù)為空或不為對象');return'輸入?yún)?shù)為空或不為對象'}returnnewObj}

測試?yán)?

vara={name:'a',age:2,info:{height:17,weight:100},arry:[1,2,3],test:{inner:{innerinner:[1,2,3]}},ud:undefined,fn:function(){console.log(1)},date:[newDate(1536627600000),newDate(1540047600000)],nan:NaN,reg:newRegExp('\\w+'),};varb=deepClone(a);b.age=28;b.name='b';b.arry[1]='lc';b.test.inner.innerinner[1]='ok';b.info.height=168;console.log(a,b);c=[1,2,3,{inner:{innerinner:[1,2,3]}}];d=deepClone(c);d[0]=0;d[3].inner.innerinner[1]=11;console.log(c,d)

推薦資料

1、JavaScript之對象序列化詳解

2披坏、javaScript中淺拷貝和深拷貝的實(shí)現(xiàn)

3态坦、你不知道的 JSON.stringify() 的威力

59人點(diǎn)贊

1-前端開發(fā)HTML/CSS學(xué)習(xí)記錄集

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市棒拂,隨后出現(xiàn)的幾起案子伞梯,更是在濱河造成了極大的恐慌,老刑警劉巖着茸,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壮锻,死亡現(xiàn)場離奇詭異,居然都是意外死亡涮阔,警方通過查閱死者的電腦和手機(jī)猜绣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敬特,“玉大人掰邢,你說我怎么就攤上這事∥袄” “怎么了辣之?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長皱炉。 經(jīng)常有香客問我怀估,道長,這世上最難降的妖魔是什么合搅? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任多搀,我火速辦了婚禮,結(jié)果婚禮上灾部,老公的妹妹穿的比我還像新娘康铭。我一直安慰自己,他們只是感情好赌髓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布从藤。 她就那樣靜靜地躺著,像睡著了一般锁蠕。 火紅的嫁衣襯著肌膚如雪夷野。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天匿沛,我揣著相機(jī)與錄音扫责,去河邊找鬼。 笑死逃呼,一個胖子當(dāng)著我的面吹牛鳖孤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抡笼,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苏揣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了推姻?” 一聲冷哼從身側(cè)響起平匈,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藏古,沒想到半個月后增炭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拧晕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年隙姿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厂捞。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡输玷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出靡馁,到底是詐尸還是另有隱情欲鹏,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布臭墨,位于F島的核電站赔嚎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胧弛。R本人自食惡果不足惜尤误,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叶圃。 院中可真熱鬧袄膏,春花似錦、人聲如沸掺冠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽德崭。三九已至斥黑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間眉厨,已是汗流浹背锌奴。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留憾股,地道東北人鹿蜀。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓箕慧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茴恰。 傳聞我的和親對象是個殘疾皇子颠焦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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