強大的JSON.stringify如何使用_第1頁
強大的JSON.stringify如何使用_第2頁
強大的JSON.stringify如何使用_第3頁
強大的JSON.stringify如何使用_第4頁
強大的JSON.stringify如何使用_第5頁
已閱讀5頁,還剩11頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

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

前言

JSON.stringify作為日常開發中經常使用的方法,你真的能靈活運用它嗎?

學習本文之前,小包想讓大家帶著幾個問題,一起來深入學習stringify。

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

整個文章的脈絡跟下面思維導圖一致,大家可以先留一下印象。

三參數

在日常編程中,我們經常JSON.stringify方法將某個對象轉換成JSON字符串形式。

conststu={

name:'zcxiaobao',

age:18

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

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

但stringify真的就這么簡單嗎?我們先來看一下MDN中對stringify的定義。

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

看完定義,小包就一驚,stringfy不止一個參數嗎?當然了,stringify有三個參數。

咱們來看一下stringify語法和參數介紹:

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

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

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

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

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

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

如果該參數為字符串(當字符串長度超過10個字母,取其前10個字母),該字符串將被作為空格

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

replacer

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

replacer作為函數

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

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

//repalcer接受兩個參數keyvalue

//keyvalue分別為對象的每個鍵值對

//因此我們可以根據鍵或者值的類型進行簡單篩選

functionreplacer(key,value){

if(typeofvalue==="string"){

returnundefined;

returnvalue;

//function可自己測試

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序列化結果為{week:45,month:7}

但如果序列化的是數組,若replacer函數返回undefined或者函數,當前值不會被忽略,而將會被null取代。

constlist=[1,'22',3]

constjsonString=JSON.stringify(list,replacer)

JSON序列化的結果為[1,null,3]

replacer作為數組

作為數組比較好理解,過濾數組中出現的鍵值。

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

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

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

九特性

特性一:undefined、函數、Symbol值

出現在非數組對象屬性值中:undefined、任意函數、Symbol值在序列化過程中將會被忽略出現在數組中:undefined、任意函數、Symbol值會被轉化為null單獨轉換時:會返回undefined

//1.對象屬性值中存在這三種值會被忽略

constobj={

name:'zc',

age:18,

//函數會被忽略

sayHello(){

console.log('helloworld')

//undefined會被忽略

wife:undefined,

//Symbol值會被忽略

id:Symbol(111),

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

//輸出結果:{"name":"zc","age":18}

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

//2.數組中這三種值會被轉化為null

constlist=[

'zc',

18,

//函數轉化為null

functionsayHello(){

console.log('helloworld')

//undefined轉換為null

undefined,

//Symbol轉換為null

Symbol(111)

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

console.log(JSON.stringify(list))

//3.這三種值單獨轉化將會返回undefined

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

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

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

console.log('helloworld')

}))//undefined

特性二:toJSON()方法

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

constobj={

name:'zc',

toJSON(){

return'returntoJSON'

//returntoJSON

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

特性三:布爾值、數字、字符串的包裝對象

布爾值、數字、字符串的包裝對象在序列化過程中會自動轉換成對應的原始值

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

//[1,"zcxiaobao",true]

特性四:NaNInfinitynull

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

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

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

//特性三講過布爾值、數字、字符串的包裝對象在序列化過程中會自動轉換成對應的原始值

//隱式類型轉換就會調用包裝類,因此會先調用Number=NaN

//之后再轉化為null

//1/0=Infinity=null

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

特性五:Date對象

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

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

JSON.stringify(newDate())

特性六:Symbol

特性一提到,Symbol類型當作值來使用時,對象、數組、單獨使用分別會被忽略、轉換為null、轉化為undefined。

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

constobj={

name:'zcxiaobao',

age:18,

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

functionreplacer(key,value){

if(typeofkey==='symbol'){

returnvalue;

//undefined

JSON.stringify(obj,replacer);

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

特性七:BigInt

JSON.stringify規定:嘗試去轉換BigInt類型的值會拋出TypeError

constbigNumber=BigInt(1)

//UncaughtTypeError:DonotknowhowtoserializeaBigInt

console.log(JSON.stringify(bigNumber))

特性八:循環引用

特性八指出:對包含循環引用的對象(對象之間相互引用,形成無限循環)執行此方法,會拋出錯誤

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

constobj={

name:'zcxiaobao',

age:18,

constloopObj={

//形成循環引用

obj.loopObj=loopObj;

JSON.stringify(obj)

/*UncaughtTypeError:ConvertingcircularstructuretoJSON

--startingatobjectwithconstructor'Object'

|property'loopObj'-objectwithconstructor'Object'

---property'obj'closesthecircle

atJSON.stringify(anonymous)

atanonymous:10:6

特性九:可枚舉屬性

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

//不可枚舉的屬性默認會被忽略

//{"age":18}

JSON.stringify(

Object.create(

null,

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

age:{value:18,enumerable:true}

六妙用

localStorage

localStorage對象用于長久保存整個網站的數據,保存的數據沒有過期時間,直到手動去刪除。通常我們以對象形式進行存儲。

單純調用localStorage對象方法

constobj={

name:'zcxiaobao',

age:18

//單純調用localStorage.setItem()

localStorage.setItem('zc',obj);

//最終返回結果是[objectObject]

//可見單純調用localStorage是失敗的

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

localStorage配合JSON.stringify方法

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

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

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

屬性過濾

來假設這樣一個場景,后端返回了一個很長的對象,對象里面屬性很多,而我們只需要其中幾個屬性,并且這幾個屬性我們要存儲到localStorage中。

方案一:解構賦值+stringify

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

constobj={

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

//解構賦值

const{a,e,f}=obj;

//存儲到localStorage

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

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

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

使用stringify的replacer參數

//借助replacer作為數組形式進行過濾

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

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

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

當replacer是數組時,可以簡單的過濾出我們所需的屬性,是一個不錯的小技巧。

三思而后行之深拷貝

使用JSON.parse(JSON.stringify)是實現對象的深拷貝最簡單暴力的方法之一。但也正如標題所言,使用該種方法的深拷貝要深思熟慮。

循環引用問題,stringify會報錯函數、undefined、Symbol會被忽略NaN、Infinity和-Infinity會被序列化成null...

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

對象的map函數

在使用數組進行編程時,我們會經常使用到map函數。有了replacer參數后,我們就可以借助此參數,實現對象的map函數。

constObjectMap=(obj,fn)={

if(typeoffn!=="function"){

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

//先調用JSON.stringify(obj,replacer)實現map功能

//然后調用JSON.parse重新轉化成對象

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

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

constobj={

a:1,

b:2,

c:3

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

if(typeofvalue==="number"){

returnvalue*2;

returnvalue;

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

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

刪除對象屬性

借助replacer函數,我們還可以刪除對象的某些屬性。

constobj={

name:'zcxiaobao',

age:18

//{"age":18}

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

//返回值為undefined時,該屬性會被忽略

if(key==='name'){

returnundefined;

returnval;

對象判斷

JSON.stringify可以將對象序列化為字符串,因此我們可以借助字符串的方法來實現簡單的對象相等判斷。

//判斷數組是否包含某對象

constnames=[

{name:'zcxiaobao'},

{name:'txtx'},

{name:'mymy'},

constzcxiaobao={name:'zcxiaobao'};

//true

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

//判斷對象是否相等

constd1={type:'div'}

constd2={type:'div'}

//true

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

數組對象去重

借助上面的思想,我們還能實現簡單的數組對象去重。

溫馨提示

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

評論

0/150

提交評論