強(qiáng)大的JSON.stringify如何使用_第1頁(yè)
強(qiáng)大的JSON.stringify如何使用_第2頁(yè)
強(qiáng)大的JSON.stringify如何使用_第3頁(yè)
強(qiáng)大的JSON.stringify如何使用_第4頁(yè)
強(qiáng)大的JSON.stringify如何使用_第5頁(yè)
已閱讀5頁(yè),還剩11頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第強(qiáng)大的JSON.stringify如何使用目錄前言三參數(shù)replacer九特性特性一:undefined、函數(shù)、Symbol值特性二:toJSON()方法特性三:布爾值、數(shù)字、字符串的包裝對(duì)象特性四:NaNInfinitynull特性五:Date對(duì)象特性六:Symbol特性七:BigInt特性八:循環(huán)引用特性九:可枚舉屬性六妙用localStorage屬性過濾三思而后行之深拷貝對(duì)象的map函數(shù)刪除對(duì)象屬性對(duì)象判斷數(shù)組對(duì)象去重參考鏈接

前言

JSON.stringify作為日常開發(fā)中經(jīng)常使用的方法,你真的能靈活運(yùn)用它嗎?

學(xué)習(xí)本文之前,小包想讓大家?guī)е鴰讉€(gè)問題,一起來深入學(xué)習(xí)stringify。

stringify函數(shù)有幾個(gè)參數(shù),每個(gè)參數(shù)分別有啥用啊stringify序列化準(zhǔn)則有哪些啊函數(shù)序列化中會(huì)如何處理null、undefined、NaN等特殊的值又會(huì)如何處理ES6后增加的Symbol類型、BigInt序列化過程中會(huì)有特別處理嗎stringify為什么不適合做深拷貝你能想到那些stringify的妙用

整個(gè)文章的脈絡(luò)跟下面思維導(dǎo)圖一致,大家可以先留一下印象。

三參數(shù)

在日常編程中,我們經(jīng)常JSON.stringify方法將某個(gè)對(duì)象轉(zhuǎn)換成JSON字符串形式。

conststu={

name:'zcxiaobao',

age:18

//{"name":"zcxiaobao","age":18}

console.log(JSON.stringify(stu));

但stringify真的就這么簡(jiǎn)單嗎?我們先來看一下MDN中對(duì)stringify的定義。

MDN中指出:JSON.stringify()方法將一個(gè)JavaScript對(duì)象或值轉(zhuǎn)換為JSON字符串,如果指定了一個(gè)replacer函數(shù),則可以選擇性地替換值,或者指定的replacer是數(shù)組,則可選擇性地僅包含數(shù)組指定的屬性。

看完定義,小包就一驚,stringfy不止一個(gè)參數(shù)嗎?當(dāng)然了,stringify有三個(gè)參數(shù)。

咱們來看一下stringify語法和參數(shù)介紹:

JSON.stringify(value[,replacer[,space]])

value:將要序列后成JSON字符串的值。replacer(可選)如果該參數(shù)是一個(gè)函數(shù),則在序列化過程中,被序列化的值的每個(gè)屬性都會(huì)經(jīng)過該函數(shù)的轉(zhuǎn)換和處理;

如果該參數(shù)是一個(gè)數(shù)組,則只有包含在這個(gè)數(shù)組中的屬性名才會(huì)被序列化到最終的JSON字符串中

如果該參數(shù)為null或者未提供,則對(duì)象所有的屬性都會(huì)被序列化。

space(可選):指定縮進(jìn)用的空白字符串,用于美化輸出如果參數(shù)是個(gè)數(shù)字,它代表有多少的空格。上限為10。

該值若小于1,則意味著沒有空格

如果該參數(shù)為字符串(當(dāng)字符串長(zhǎng)度超過10個(gè)字母,取其前10個(gè)字母),該字符串將被作為空格

如果該參數(shù)沒有提供(或者為null),將沒有空格

replacer

我們來嘗試一下replacer的使用。

replacer作為函數(shù)

replacer作為函數(shù),它有兩個(gè)參數(shù),鍵(key)和值(value),并且兩個(gè)參數(shù)都會(huì)被序列化。

在開始時(shí),replacer函數(shù)會(huì)被傳入一個(gè)空字符串作為key值,代表著要被stringify的這個(gè)對(duì)象。理解這點(diǎn)很重要,replacer函數(shù)并非是上來就把對(duì)象解析成鍵值對(duì)形式,而是先傳入了待序列化對(duì)象。隨后每個(gè)對(duì)象或數(shù)組上的屬性會(huì)被依次傳入。如果函數(shù)返回值為undefined或者函數(shù)時(shí),該屬性值會(huì)被過濾掉,其余按照返回規(guī)則。

//repalcer接受兩個(gè)參數(shù)keyvalue

//keyvalue分別為對(duì)象的每個(gè)鍵值對(duì)

//因此我們可以根據(jù)鍵或者值的類型進(jìn)行簡(jiǎn)單篩選

functionreplacer(key,value){

if(typeofvalue==="string"){

returnundefined;

returnvalue;

//function可自己測(cè)試

functionreplacerFunc(key,value){

if(typeofvalue==="string"){

return()=

returnvalue;

constfoo={foundation:"Mozilla",model:"box",week:45,transport:"car",month:7};

constjsonString=JSON.stringify(foo,replacer);

JSON序列化結(jié)果為{week:45,month:7}

但如果序列化的是數(shù)組,若replacer函數(shù)返回undefined或者函數(shù),當(dāng)前值不會(huì)被忽略,而將會(huì)被null取代。

constlist=[1,'22',3]

constjsonString=JSON.stringify(list,replacer)

JSON序列化的結(jié)果為[1,null,3]

replacer作為數(shù)組

作為數(shù)組比較好理解,過濾數(shù)組中出現(xiàn)的鍵值。

constfoo={foundation:"Mozilla",model:"box",week:45,transport:"car",month:7};

constjsonString=JSON.stringify(foo,['week','month']);

JSON序列化結(jié)果為{week:45,month:7},只保留week和month屬性值。

九特性

特性一:undefined、函數(shù)、Symbol值

出現(xiàn)在非數(shù)組對(duì)象屬性值中:undefined、任意函數(shù)、Symbol值在序列化過程中將會(huì)被忽略出現(xiàn)在數(shù)組中:undefined、任意函數(shù)、Symbol值會(huì)被轉(zhuǎn)化為null單獨(dú)轉(zhuǎn)換時(shí):會(huì)返回undefined

//1.對(duì)象屬性值中存在這三種值會(huì)被忽略

constobj={

name:'zc',

age:18,

//函數(shù)會(huì)被忽略

sayHello(){

console.log('helloworld')

//undefined會(huì)被忽略

wife:undefined,

//Symbol值會(huì)被忽略

id:Symbol(111),

//[Symbol('zc')]:'zc',

//輸出結(jié)果:{"name":"zc","age":18}

console.log(JSON.stringify(obj));

//2.數(shù)組中這三種值會(huì)被轉(zhuǎn)化為null

constlist=[

'zc',

18,

//函數(shù)轉(zhuǎn)化為null

functionsayHello(){

console.log('helloworld')

//undefined轉(zhuǎn)換為null

undefined,

//Symbol轉(zhuǎn)換為null

Symbol(111)

//["zc",18,null,null,null]

console.log(JSON.stringify(list))

//3.這三種值單獨(dú)轉(zhuǎn)化將會(huì)返回undefined

console.log(JSON.stringify(undefined))//undefined

console.log(JSON.stringify(Symbol(111)))//undefined

console.log(JSON.stringify(functionsayHello(){

console.log('helloworld')

}))//undefined

特性二:toJSON()方法

轉(zhuǎn)換值如果有toJSON()方法,toJSON()方法返回什么值,序列化結(jié)果就返回什么值,其余值會(huì)被忽略。

constobj={

name:'zc',

toJSON(){

return'returntoJSON'

//returntoJSON

console.log(JSON.stringify(obj));

特性三:布爾值、數(shù)字、字符串的包裝對(duì)象

布爾值、數(shù)字、字符串的包裝對(duì)象在序列化過程中會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值

JSON.stringify([newNumber(1),newString("zcxiaobao"),newBoolean(true)]);

//[1,"zcxiaobao",true]

特性四:NaNInfinitynull

特性四主要針對(duì)JavaScript里面的特殊值,例如Number類型里的NaN和Infinity及null。此三種數(shù)值序列化過程中都會(huì)被當(dāng)做null。

//[null,null,null,null,null]

JSON.stringify([null,NaN,-NaN,Infinity,-Infinity])

//特性三講過布爾值、數(shù)字、字符串的包裝對(duì)象在序列化過程中會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值

//隱式類型轉(zhuǎn)換就會(huì)調(diào)用包裝類,因此會(huì)先調(diào)用Number=NaN

//之后再轉(zhuǎn)化為null

//1/0=Infinity=null

JSON.stringify([Number('123a'),+'123a',1/0])

特性五:Date對(duì)象

Date對(duì)象上部署了toJSON方法(同Date.toISOString())將其轉(zhuǎn)換為字符串,因此JSON.stringify()將會(huì)序列化Date的值為時(shí)間格式字符串。

//"2025-03-06T08:24:56.138Z"

JSON.stringify(newDate())

特性六:Symbol

特性一提到,Symbol類型當(dāng)作值來使用時(shí),對(duì)象、數(shù)組、單獨(dú)使用分別會(huì)被忽略、轉(zhuǎn)換為null、轉(zhuǎn)化為undefined。

同樣的,所有以Symbol為屬性鍵的屬性都會(huì)被完全忽略掉,即便replacer參數(shù)中強(qiáng)制指定包含了它們。

constobj={

name:'zcxiaobao',

age:18,

[Symbol('lyl')]:'unique'

functionreplacer(key,value){

if(typeofkey==='symbol'){

returnvalue;

//undefined

JSON.stringify(obj,replacer);

通過上面案例,我們可以看出,雖然我們通過replacer強(qiáng)行指定了返回Symbol類型值,但最終還是會(huì)被忽略掉。

特性七:BigInt

JSON.stringify規(guī)定:嘗試去轉(zhuǎn)換BigInt類型的值會(huì)拋出TypeError

constbigNumber=BigInt(1)

//UncaughtTypeError:DonotknowhowtoserializeaBigInt

console.log(JSON.stringify(bigNumber))

特性八:循環(huán)引用

特性八指出:對(duì)包含循環(huán)引用的對(duì)象(對(duì)象之間相互引用,形成無限循環(huán))執(zhí)行此方法,會(huì)拋出錯(cuò)誤

日常開發(fā)中深拷貝最簡(jiǎn)單暴力的方式就是使用JSON.parse(JSON.stringify(obj)),但此方法下的深拷貝存在巨坑,關(guān)鍵問題就在于stringify無法處理循環(huán)引用問題。

constobj={

name:'zcxiaobao',

age:18,

constloopObj={

//形成循環(huán)引用

obj.loopObj=loopObj;

JSON.stringify(obj)

/*UncaughtTypeError:ConvertingcircularstructuretoJSON

--startingatobjectwithconstructor'Object'

|property'loopObj'-objectwithconstructor'Object'

---property'obj'closesthecircle

atJSON.stringify(anonymous)

atanonymous:10:6

特性九:可枚舉屬性

對(duì)于對(duì)象(包括Map/Set/WeakMap/WeakSet)的序列化,除了上文講到的一些情況,stringify也明確規(guī)定,僅會(huì)序列化可枚舉的屬性

//不可枚舉的屬性默認(rèn)會(huì)被忽略

//{"age":18}

JSON.stringify(

Object.create(

null,

name:{value:'zcxiaobao',enumerable:false},

age:{value:18,enumerable:true}

六妙用

localStorage

localStorage對(duì)象用于長(zhǎng)久保存整個(gè)網(wǎng)站的數(shù)據(jù),保存的數(shù)據(jù)沒有過期時(shí)間,直到手動(dòng)去刪除。通常我們以對(duì)象形式進(jìn)行存儲(chǔ)。

單純調(diào)用localStorage對(duì)象方法

constobj={

name:'zcxiaobao',

age:18

//單純調(diào)用localStorage.setItem()

localStorage.setItem('zc',obj);

//最終返回結(jié)果是[objectObject]

//可見單純調(diào)用localStorage是失敗的

console.log(localStorage.getItem('zc'))

localStorage配合JSON.stringify方法

localStorage.setItem('zc',JSON.stringify(obj));

//最終返回結(jié)果是{name:'zcxiaobao',age:18}

console.log(JSON.parse(localStorage.getItem('zc')))

屬性過濾

來假設(shè)這樣一個(gè)場(chǎng)景,后端返回了一個(gè)很長(zhǎng)的對(duì)象,對(duì)象里面屬性很多,而我們只需要其中幾個(gè)屬性,并且這幾個(gè)屬性我們要存儲(chǔ)到localStorage中。

方案一:解構(gòu)賦值+stringify

//我們只需要a,e,f屬性

constobj={

a:1,b:2,c:3,d:4,e:5,f:6,g:7

//解構(gòu)賦值

const{a,e,f}=obj;

//存儲(chǔ)到localStorage

localStorage.setItem('zc',JSON.stringify({a,e,f}))

//{"a":1,"e":5,"f":6}

console.log(localStorage.getItem('zc'))

使用stringify的replacer參數(shù)

//借助replacer作為數(shù)組形式進(jìn)行過濾

localStorage.setItem('zc',JSON.stringify(obj,['a','e','f']))

//{"a":1,"e":5,"f":6}

console.log(localStorage.getItem('zc'))

當(dāng)replacer是數(shù)組時(shí),可以簡(jiǎn)單的過濾出我們所需的屬性,是一個(gè)不錯(cuò)的小技巧。

三思而后行之深拷貝

使用JSON.parse(JSON.stringify)是實(shí)現(xiàn)對(duì)象的深拷貝最簡(jiǎn)單暴力的方法之一。但也正如標(biāo)題所言,使用該種方法的深拷貝要深思熟慮。

循環(huán)引用問題,stringify會(huì)報(bào)錯(cuò)函數(shù)、undefined、Symbol會(huì)被忽略NaN、Infinity和-Infinity會(huì)被序列化成null...

因此在使用JSON.parse(JSON.stringify)做深拷貝時(shí),一定要深思熟慮。如果沒有上述隱患,JSON.parse(JSON.stringify)是一個(gè)可行的深拷貝方案。

對(duì)象的map函數(shù)

在使用數(shù)組進(jìn)行編程時(shí),我們會(huì)經(jīng)常使用到map函數(shù)。有了replacer參數(shù)后,我們就可以借助此參數(shù),實(shí)現(xiàn)對(duì)象的map函數(shù)。

constObjectMap=(obj,fn)={

if(typeoffn!=="function"){

thrownewTypeError(`${fn}isnotafunction!`);

//先調(diào)用JSON.stringify(obj,replacer)實(shí)現(xiàn)map功能

//然后調(diào)用JSON.parse重新轉(zhuǎn)化成對(duì)象

returnJSON.parse(JSON.stringify(obj,fn));

//例如下面給obj對(duì)象的屬性值乘以2

constobj={

a:1,

b:2,

c:3

console.log(ObjectMap(obj,(key,val)={

if(typeofvalue==="number"){

returnvalue*2;

returnvalue;

很多同學(xué)有可能會(huì)很奇怪,為什么里面還需要多加一部判斷,直接returnvalue*2不可嗎?

上文講過,replacer函數(shù)首先傳入的是待序列化對(duì)象,對(duì)象*2=NaN=toJSON(NaN)=undefined=被忽略,就沒有后續(xù)的鍵值對(duì)解析了。

刪除對(duì)象屬性

借助replacer函數(shù),我們還可以刪除對(duì)象的某些屬性。

constobj={

name:'zcxiaobao',

age:18

//{"age":18}

JSON.stringify(obj,(key,val)={

//返回值為undefined時(shí),該屬性會(huì)被忽略

if(key==='name'){

returnundefined;

returnval;

對(duì)象判斷

JSON.stringify可以將對(duì)象序列化為字符串,因此我們可以借助字符串的方法來實(shí)現(xiàn)簡(jiǎn)單的對(duì)象相等判斷。

//判斷數(shù)組是否包含某對(duì)象

constnames=[

{name:'zcxiaobao'},

{name:'txtx'},

{name:'mymy'},

constzcxiaobao={name:'zcxiaobao'};

//true

JSON.stringify(names).includes(JSON.stringify(zcxiaobao))

//判斷對(duì)象是否相等

constd1={type:'div'}

constd2={type:'div'}

//true

JSON.stringify(d1)===JSON.stringify(d2);

數(shù)組對(duì)象去重

借助上面的思想,我們還能實(shí)現(xiàn)簡(jiǎn)單的數(shù)組對(duì)象去重。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論