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)
推薦資料
2披坏、javaScript中淺拷貝和深拷貝的實(shí)現(xiàn)
3态坦、你不知道的 JSON.stringify() 的威力
59人點(diǎn)贊