<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          就因為JSON.stringify,我的年終獎差點打水漂了

          共 13151字,需瀏覽 27分鐘

           ·

          2021-10-14 23:56

          ?

          ?????關注《前端陽光》,加入技術交流群?
          ?


          前言

          ?

          開發(fā)要對線上環(huán)境有一顆敬畏之心,任何一個點都有可能導致線上故障,也有可能讓你的年終獎泡湯(⊙︿⊙)。比如使用了JSON.stringify,這個無比熟悉但又無比陌生的API。

          ?

          看完本文您可以收獲:

          1. 了解一個差點讓我年終獎打水漂的悲傷的故事o(╥﹏╥)o
          2. 學習JSON.stringify的9大特性和轉換規(guī)則 「(重點)」
          3. 了解如何判斷一個對象是否存在循環(huán)引用 「(重點)」
          4. 從零開始手寫一個JSON.stringify 「(重點)」
          5. 等等

          說一個悲傷的故事

          ?

          最近組內有個小伙伴離職了,他所負責的一塊業(yè)務由我去維護,結果剛接手,代碼還沒捂熱乎,差點背上p0的鍋。請讓我花一點時間和你說清楚來龍去脈。

          ?

          悲傷伊始

          ?

          這一天「胖頭魚」正徜徉在代碼的海洋不可自拔,突然被拉進了一個線上問題排查群,群里不可謂不熱鬧。

          ?

          「產(chǎn)品同學」在訴苦:線上用戶不能提交表單了,帶來了好多客訴,估計會是p0故障,希望盡快解決。

          「測試同學」在納悶:這個場景測試和預發(fā)環(huán)境明明驗過的,怎么線上就不行了。

          「后端同學」在講原因:接口缺少了value字段,導致出錯了。

          就是木有人說問題怎么解決!!!

          就是木有人說問題怎么解決!!!

          就是木有人說問題怎么解決!!!

          這樣的場景不知道你是不是也似曾相識呢?o(╥﹏╥)o,不管咋說第一要務還是先把線上問題解決掉,減少持續(xù)影響,趕緊把交接的代碼翻出來,開始了排查過程。

          問題原因

          ?

          如下圖:有這樣一個動態(tài)表單搜集頁面,用戶選擇或者填寫了信息之后(各字段非必填情況下也可以直接提交),接著前端把數(shù)據(jù)發(fā)送給后端,結束,看起來沒有多復雜的邏輯。

          ?
          image.png

          「直接錯誤原因」

          ?

          非必填情況下,signInfo字段中經(jīng)過JSON.stringify后的字符串對象缺少value key,導致后端parse之后無法正確讀取value值,進而報接口系統(tǒng)異常,用戶無法進行下一步動作。

          ?
          //?異常入?yún)?shù)據(jù),數(shù)組字符串中沒有value?key
          {
          ??signInfo:?'[{"fieldId":539},{"fieldId":540},{"fieldId":546,"value":"10:30"}]'
          }

          //?正常入?yún)?shù)據(jù)
          {
          ??signInfo:?'[{"fieldId":539,"value":"銀卡"},{"fieldId":540,"value":"2021-03-01"},{"fieldId":546,"value":"10:30"}]'
          }

          「異常數(shù)據(jù)是如何產(chǎn)生的」

          //?默認情況下數(shù)據(jù)是這樣的
          let?signInfo?=?[
          ??{
          ????fieldId:?539,
          ????value:?undefined
          ??},
          ??{
          ????fieldId:?540,
          ????value:?undefined
          ??},
          ??{
          ????fieldId:?546,
          ????value:?undefined
          ??},
          ]
          //?經(jīng)過JSON.stringify之后的數(shù)據(jù),少了value?key,導致后端無法讀取value值進行報錯
          //?具體原因是`undefined`、`任意的函數(shù)`以及`symbol值`,出現(xiàn)在`非數(shù)組對象`的屬性值中時在序列化過程中會被忽略
          console.log(JSON.stringify(signInfo))
          //?'[{"fieldId":539},{"fieldId":540},{"fieldId":546}]'

          解決方案

          ?

          問題的原因找到了,解決方式 「(這里只講前端的解決方案,當然也可以由后端解決)」 也很簡單,將value值為undefined的項轉化為空字符串再提交即可。

          ?

          「方案一:新開一個對象處理」

          let?signInfo?=?[
          ??{
          ????fieldId:?539,
          ????value:?undefined
          ??},
          ??{
          ????fieldId:?540,
          ????value:?undefined
          ??},
          ??{
          ????fieldId:?546,
          ????value:?undefined
          ??},
          ]

          let?newSignInfo?=?signInfo.map((it)?=>?{
          ??const?value?=?typeof?it.value?===?'undefined'???''?:?it.value
          ??return?{
          ????...it,
          ????value
          ??}
          })

          console.log(JSON.stringify(newSignInfo))
          //?'[{"fieldId":539,"value":""},{"fieldId":540,"value":""},{"fieldId":546,"value":""}]'

          方案二:利用JSON.stringify第二個參數(shù),直接處理

          ?

          方案一的缺陷是需要新開一個對象進行一頓操作才能解決,不夠優(yōu)雅

          ?
          let?signInfo?=?[
          ??{
          ????fieldId:?539,
          ????value:?undefined
          ??},
          ??{
          ????fieldId:?540,
          ????value:?undefined
          ??},
          ??{
          ????fieldId:?546,
          ????value:?undefined
          ??},
          ]

          //?判斷到value為undefined,返回空字符串即可
          JSON.stringify(signInfo,?(key,?value)?=>?typeof?value?===?'undefined'???''?:?value)
          //?'[{"fieldId":539,"value":""},{"fieldId":540,"value":""},{"fieldId":546,"value":""}]'

          故事后續(xù)

          ?

          原本這是一個已經(jīng)上線有一段時間的頁面,為何會突然出現(xiàn)這個問題,之前卻沒有呢?仔細詢問下,原來是中途產(chǎn)品同學提了一個小的優(yōu)化點,離職的小伙伴感覺點比較小直接就改了代碼上線了,未曾想出現(xiàn)了線上問題。

          ?

          后面針對這件事從產(chǎn)品到測試、到后端、到前端單獨做了一個完整的復盤,細節(jié)就不再展開說了。

          因為從發(fā)現(xiàn)問題到解決問題速度較快、影響用戶數(shù)較少,還未達到問責程度,「俺的年終獎可算是保住了o(╥﹏╥)o。」

          重學JSON.stringify

          ?

          經(jīng)過這件事情,我覺得有必要重新審視一下JSON.stringify這個方法,徹底搞清楚轉換規(guī)則,并嘗試手寫實現(xiàn)一個JSON.stringify

          ?

          如果你曾遇到和我一樣的問題,歡迎一起來重新學習一次,一定會有不一樣的收獲噢!

          學透JSON.stringify

          ?

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

          ?

          以下信息來自MDN

          語法

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

          參數(shù)[1]

          • value

            將要序列化成 一個 JSON 字符串的值。

          • replacer?可選

            1. 如果該參數(shù)是一個函數(shù),則在序列化過程中,被序列化的值的每個屬性都會經(jīng)過該函數(shù)的轉換和處理;
            2. 如果該參數(shù)是一個數(shù)組,則只有包含在這個數(shù)組中的屬性名才會被序列化到最終的 JSON 字符串中;
            3. 如果該參數(shù)為 null 或者未提供,則對象所有的屬性都會被序列化。
          • space?可選

            1. 指定縮進用的空白字符串,用于美化輸出(pretty-print);
            2. 如果參數(shù)是個數(shù)字,它代表有多少的空格;上限為10。
            3. 該值若小于1,則意味著沒有空格;
            4. 如果該參數(shù)為字符串(當字符串長度超過10個字母,取其前10個字母),該字符串將被作為空格;
            5. 如果該參數(shù)沒有提供(或者為 null),將沒有空格。

          「返回值」

          一個表示給定值的JSON字符串。

          異常[2]

          • 當在循環(huán)引用時會拋出異常TypeError?("cyclic object value")(循環(huán)對象值)
          • 當嘗試去轉換?BigInt?類型的值會拋出TypeError?("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化).

          基本使用

          「注意」

          1. JSON.stringify可以轉換對象或者值(平常用的更多的是轉換對象)
          2. 可以指定replacer為函數(shù)選擇性的地替換
          3. 也可以指定replacer為數(shù)組,可轉換指定的屬性

          這里僅僅是NDN上關于JSON.stringify其中最基礎的說明,咱們先打個碼試試這幾個特性

          //?1.?轉換對象
          console.log(JSON.stringify({?name:?'前端胖頭魚',?sex:?'boy'?}))?//?'{"name":"前端胖頭魚","sex":"boy"}'

          //?2.?轉換普通值
          console.log(JSON.stringify('前端胖頭魚'))?//?"前端胖頭魚"
          console.log(JSON.stringify(1))?//?"1"
          console.log(JSON.stringify(true))?//?"true"
          console.log(JSON.stringify(null))?//?"null"

          //?3.?指定replacer函數(shù)
          console.log(JSON.stringify({?name:?'前端胖頭魚',?sex:?'boy',?age:?100?},?(key,?value)?=>?{
          ??return?typeof?value?===?'number'???undefined?:?value
          }))
          //?'{"name":"前端胖頭魚","sex":"boy"}'

          //?4.?指定數(shù)組
          console.log(JSON.stringify({?name:?'前端胖頭魚',?sex:?'boy',?age:?100?},?[?'name'?]))
          //?'{"name":"前端胖頭魚"}'

          //?5.?指定space(美化輸出)
          console.log(JSON.stringify({?name:?'前端胖頭魚',?sex:?'boy',?age:?100?}))
          //?'{"name":"前端胖頭魚","sex":"boy","age":100}'
          console.log(JSON.stringify({?name:?'前端胖頭魚',?sex:?'boy',?age:?100?},?null?,?2))
          /*
          {
          ??"name":?"前端胖頭魚",
          ??"sex":?"boy",
          ??"age":?100
          }
          */

          9大特性要記住

          ?

          以前僅僅是使用了這個方法,卻沒有詳細了解他的轉換規(guī)則,居然有9個之多。

          ?

          特性一

          1. undefined任意的函數(shù)以及symbol值,出現(xiàn)在非數(shù)組對象的屬性值中時在序列化過程中會被忽略
          2. undefined任意的函數(shù)以及symbol值出現(xiàn)在數(shù)組中時會被轉換成?null
          3. undefined任意的函數(shù)以及symbol值單獨轉換時,會返回 undefined
          //?1.?對象中存在這三種值會被忽略
          console.log(JSON.stringify({
          ??name:?'前端胖頭魚',
          ??sex:?'boy',
          ??//?函數(shù)會被忽略
          ??showName?()?{
          ????console.log('前端胖頭魚')
          ??},
          ??//?undefined會被忽略
          ??age:?undefined,
          ??//?Symbol會被忽略
          ??symbolName:?Symbol('前端胖頭魚')
          }))
          //?'{"name":"前端胖頭魚","sex":"boy"}'

          //?2.?數(shù)組中存在著三種值會被轉化為null
          console.log(JSON.stringify([
          ??'前端胖頭魚',
          ??'boy',
          ??//?函數(shù)會被轉化為null
          ??function?showName?()?{
          ????console.log('前端胖頭魚')
          ??},
          ??//undefined會被轉化為null
          ??undefined,
          ??//Symbol會被轉化為null
          ??Symbol('前端胖頭魚')
          ]))
          //?'["前端胖頭魚","boy",null,null,null]'

          //?3.單獨轉換會返回undefined
          console.log(JSON.stringify(
          ??function?showName?()?{
          ????console.log('前端胖頭魚')
          ??}
          ))?//?undefined
          console.log(JSON.stringify(undefined))?//?undefined
          console.log(JSON.stringify(Symbol('前端胖頭魚')))?//?undefined

          特性二

          ?

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

          ?
          console.log(JSON.stringify([new?Number(1),?new?String("前端胖頭魚"),?new?Boolean(false)]))
          //?'[1,"前端胖頭魚",false]'

          特性三

          ?

          所有以symbol為屬性鍵的屬性都會被完全忽略掉,即便?replacer?參數(shù)中強制指定包含了它們。

          ?
          console.log(JSON.stringify({
          ??name:?Symbol('前端胖頭魚'),
          }))
          //?'{}'
          console.log(JSON.stringify({
          ??[?Symbol('前端胖頭魚')?]:?'前端胖頭魚',
          },?(key,?value)?=>?{
          ??if?(typeof?key?===?'symbol')?{
          ????return?value
          ??}
          }))
          //?undefined

          特性四

          ?

          NaN 和 Infinity 格式的數(shù)值及 null 都會被當做 null。

          ?
          console.log(JSON.stringify({
          ??age:?NaN,
          ??age2:?Infinity,
          ??name:?null
          }))
          //?'{"age":null,"age2":null,"name":null}'

          特性五

          ?

          轉換值如果有 toJSON() 方法,該方法定義什么值將被序列化。

          ?
          const?toJSONObj?=?{
          ??name:?'前端胖頭魚',
          ??toJSON?()?{
          ????return?'JSON.stringify'
          ??}
          }

          console.log(JSON.stringify(toJSONObj))
          //?"JSON.stringify"

          特性六

          ?

          Date 日期調用了 toJSON() 將其轉換為了 string 字符串(同Date.toISOString()),因此會被當做字符串處理。

          ?
          const?d?=?new?Date()

          console.log(d.toJSON())?//?2021-10-05T14:01:23.932Z
          console.log(JSON.stringify(d))?//?"2021-10-05T14:01:23.932Z"

          特性七

          ?

          對包含循環(huán)引用的對象(對象之間相互引用,形成無限循環(huán))執(zhí)行此方法,會拋出錯誤。

          ?
          let?cyclicObj?=?{
          ??name:?'前端胖頭魚',
          }

          cyclicObj.obj?=?cyclicObj

          console.log(JSON.stringify(cyclicObj))
          //?Converting?circular?structure?to?JSON

          特性八

          ?

          其他類型的對象,包括 Map/Set/WeakMap/WeakSet,僅會序列化可枚舉的屬性

          ?
          let?enumerableObj?=?{}

          Object.defineProperties(enumerableObj,?{
          ??name:?{
          ????value:?'前端胖頭魚',
          ????enumerable:?true
          ??},
          ??sex:?{
          ????value:?'boy',
          ????enumerable:?false
          ??},
          })

          console.log(JSON.stringify(enumerableObj))
          //?'{"name":"前端胖頭魚"}'

          特性九

          ?

          當嘗試去轉換?BigInt?類型的值會拋出錯誤

          ?
          const?alsoHuge?=?BigInt(9007199254740991)

          console.log(JSON.stringify(alsoHuge))
          //?TypeError:?Do?not?know?how?to?serialize?a?BigInt

          手寫一個JSON.stringify

          ?

          終于重新學完JSON.stringify的眾多特性啦!咱們根據(jù)這些特性來手寫一個簡單版本的吧(「無replacer函數(shù)和space」

          ?

          源碼實現(xiàn)

          const?jsonstringify?=?(data)?=>?{
          ??//?確認一個對象是否存在循環(huán)引用
          ??const?isCyclic?=?(obj)?=>?{
          ??//?使用Set數(shù)據(jù)類型來存儲已經(jīng)檢測過的對象
          ??let?stackSet?=?new?Set()
          ??let?detected?=?false

          ??const?detect?=?(obj)?=>?{
          ????//?不是對象類型的話,可以直接跳過
          ????if?(obj?&&?typeof?obj?!=?'object')?{
          ??????return
          ????}
          ????//?當要檢查的對象已經(jīng)存在于stackSet中時,表示存在循環(huán)引用
          ????if?(stackSet.has(obj))?{
          ??????return?detected?=?true
          ????}
          ????//?將當前obj存如stackSet
          ????stackSet.add(obj)

          ????for?(let?key?in?obj)?{
          ??????//?對obj下的屬性進行挨個檢測
          ??????if?(obj.hasOwnProperty(key))?{
          ????????detect(obj[key])
          ??????}
          ????}
          ????//?平級檢測完成之后,將當前對象刪除,防止誤判
          ????/*
          ??????例如:對象的屬性指向同一引用,如果不刪除的話,會被認為是循環(huán)引用
          ??????let?tempObj?=?{
          ????????name:?'前端胖頭魚'
          ??????}
          ??????let?obj4?=?{
          ????????obj1:?tempObj,
          ????????obj2:?tempObj
          ??????}
          ????*/

          ????stackSet.delete(obj)
          ??}

          ??detect(obj)

          ??return?detected
          }

          ??//?特性七:
          ??//?對包含循環(huán)引用的對象(對象之間相互引用,形成無限循環(huán))執(zhí)行此方法,會拋出錯誤。
          ??if?(isCyclic(data))?{
          ????throw?new?TypeError('Converting?circular?structure?to?JSON')
          ??}

          ??//?特性九:
          ??//?當嘗試去轉換?BigInt?類型的值會拋出錯誤
          ??if?(typeof?data?===?'bigint')?{
          ????throw?new?TypeError('Do?not?know?how?to?serialize?a?BigInt')
          ??}

          ??const?type?=?typeof?data
          ??const?commonKeys1?=?['undefined',?'function',?'symbol']
          ??const?getType?=?(s)?=>?{
          ????return?Object.prototype.toString.call(s).replace(/\[object?(.*?)\]/,?'$1').toLowerCase()
          ??}

          ??//?非對象
          ??if?(type?!==?'object'?||?data?===?null)?{
          ????let?result?=?data
          ????//?特性四:
          ????// NaN 和 Infinity 格式的數(shù)值及 null 都會被當做 null。
          ????if?([NaN,?Infinity,?null].includes(data))?{
          ??????result?=?'null'
          ??????//?特性一:
          ??????//?`undefined`、`任意的函數(shù)`以及`symbol值`被`單獨轉換`時,會返回?undefined
          ????}?else?if?(commonKeys1.includes(type))?{
          ??????//?直接得到undefined,并不是一個字符串'undefined'
          ??????return?undefined
          ????}?else?if?(type?===?'string')?{
          ??????result?=?'"'?+?data?+?'"'
          ????}

          ????return?String(result)
          ??}?else?if?(type?===?'object')?{
          ????//?特性五:
          ????//?轉換值如果有?toJSON()?方法,該方法定義什么值將被序列化
          ????//?特性六:
          ????// Date 日期調用了 toJSON()?將其轉換為了 string 字符串(同Date.toISOString()),因此會被當做字符串處理。
          ????if?(typeof?data.toJSON?===?'function')?{
          ??????return?jsonstringify(data.toJSON())
          ????}?else?if?(Array.isArray(data))?{
          ??????let?result?=?data.map((it)?=>?{
          ????????//?特性一:
          ????????//?`undefined`、`任意的函數(shù)`以及`symbol值`出現(xiàn)在`數(shù)組`中時會被轉換成?`null`
          ????????return?commonKeys1.includes(typeof?it)???'null'?:?jsonstringify(it)
          ??????})

          ??????return?`[${result}]`.replace(/'/g,?'"')
          ????}?else?{
          ??????//?特性二:
          ??????//?布爾值、數(shù)字、字符串的包裝對象在序列化過程中會自動轉換成對應的原始值。
          ??????if?(['boolean',?'number'].includes(getType(data)))?{
          ????????return?String(data)
          ??????}?else?if?(getType(data)?===?'string')?{
          ????????return?'"'?+?data?+?'"'
          ??????}?else?{
          ????????let?result?=?[]
          ????????//?特性八
          ????????//?其他類型的對象,包括?Map/Set/WeakMap/WeakSet,僅會序列化可枚舉的屬性
          ????????Object.keys(data).forEach((key)?=>?{
          ??????????//?特性三:
          ??????????//?所有以symbol為屬性鍵的屬性都會被完全忽略掉,即便 replacer 參數(shù)中強制指定包含了它們。
          ??????????if?(typeof?key?!==?'symbol')?{
          ????????????const?value?=?data[key]
          ????????????//?特性一
          ????????????//?`undefined`、`任意的函數(shù)`以及`symbol值`,出現(xiàn)在`非數(shù)組對象`的屬性值中時在序列化過程中會被忽略
          ????????????if?(!commonKeys1.includes(typeof?value))?{
          ??????????????result.push(`"${key}":${jsonstringify(value)}`)
          ????????????}
          ??????????}
          ????????})

          ????????return?`{${result}}`.replace(/'/,?'"')
          ??????}
          ????}
          ??}
          }


          測試一把

          //?1.?測試一下基本輸出
          console.log(jsonstringify(undefined))?//?undefined?
          console.log(jsonstringify(()?=>?{?}))?//?undefined
          console.log(jsonstringify(Symbol('前端胖頭魚')))?//?undefined
          console.log(jsonstringify((NaN)))?//?null
          console.log(jsonstringify((Infinity)))?//?null
          console.log(jsonstringify((null)))?//?null
          console.log(jsonstringify({
          ??name:?'前端胖頭魚',
          ??toJSON()?{
          ????return?{
          ??????name:?'前端胖頭魚2',
          ??????sex:?'boy'
          ????}
          ??}
          }))
          //?{"name":"前端胖頭魚2","sex":"boy"}

          //?2.?和原生的JSON.stringify轉換進行比較
          console.log(jsonstringify(null)?===?JSON.stringify(null));
          //?true
          console.log(jsonstringify(undefined)?===?JSON.stringify(undefined));
          //?true
          console.log(jsonstringify(false)?===?JSON.stringify(false));
          //?true
          console.log(jsonstringify(NaN)?===?JSON.stringify(NaN));
          //?true
          console.log(jsonstringify(Infinity)?===?JSON.stringify(Infinity));
          //?true
          let?str?=?"前端胖頭魚";
          console.log(jsonstringify(str)?===?JSON.stringify(str));
          //?true
          let?reg?=?new?RegExp("\w");
          console.log(jsonstringify(reg)?===?JSON.stringify(reg));
          //?true
          let?date?=?new?Date();
          console.log(jsonstringify(date)?===?JSON.stringify(date));
          //?true
          let?sym?=?Symbol('前端胖頭魚');
          console.log(jsonstringify(sym)?===?JSON.stringify(sym));
          //?true
          let?array?=?[1,?2,?3];
          console.log(jsonstringify(array)?===?JSON.stringify(array));
          //?true
          let?obj?=?{
          ??name:?'前端胖頭魚',
          ??age:?18,
          ??attr:?['coding',?123],
          ??date:?new?Date(),
          ??uni:?Symbol(2),
          ??sayHi:?function?()?{
          ????console.log("hello?world")
          ??},
          ??info:?{
          ????age:?16,
          ????intro:?{
          ??????money:?undefined,
          ??????job:?null
          ????}
          ??},
          ??pakingObj:?{
          ????boolean:?new?Boolean(false),
          ????string:?new?String('前端胖頭魚'),
          ????number:?new?Number(1),
          ??}
          }
          console.log(jsonstringify(obj)?===?JSON.stringify(obj))?
          //?true
          console.log((jsonstringify(obj)))
          //?{"name":"前端胖頭魚","age":18,"attr":["coding",123],"date":"2021-10-06T14:59:58.306Z","info":{"age":16,"intro":{"job":null}},"pakingObj":{"boolean":false,"string":"前端胖頭魚","number":1}}
          console.log(JSON.stringify(obj))
          //?{"name":"前端胖頭魚","age":18,"attr":["coding",123],"date":"2021-10-06T14:59:58.306Z","info":{"age":16,"intro":{"job":null}},"pakingObj":{"boolean":false,"string":"前端胖頭魚","number":1}}

          //?3.?測試可遍歷對象
          let?enumerableObj?=?{}

          Object.defineProperties(enumerableObj,?{
          ??name:?{
          ????value:?'前端胖頭魚',
          ????enumerable:?true
          ??},
          ??sex:?{
          ????value:?'boy',
          ????enumerable:?false
          ??},
          })

          console.log(jsonstringify(enumerableObj))
          //?{"name":"前端胖頭魚"}

          //?4.?測試循環(huán)引用和Bigint

          let?obj1?=?{?a:?'aa'?}
          let?obj2?=?{?name:?'前端胖頭魚',?a:?obj1,?b:?obj1?}
          obj2.obj?=?obj2

          console.log(jsonstringify(obj2))
          //?TypeError:?Converting?circular?structure?to?JSON
          console.log(jsonStringify(BigInt(1)))
          //?TypeError:?Do?not?know?how?to?serialize?a?BigInt

          通過上面測試可以看出,jsonstringify基本和JSON.stringify表現(xiàn)一致,(也有可能測試用例不夠全面,歡迎提出一起學習)

          結尾

          ?

          因為一個BUG,重學了JSON.stringify,了解到原來它還有這么多平時沒有注意到特性,前端娛樂圈水太深了,愿大家都被溫柔以待,少些bug,多些關懷。晚安

          ?

          Reference

          [1]

          Permalink to 參數(shù): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#parameters

          [2]

          Permalink to 異常: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#%E5%BC%82%E5%B8%B8


          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  三级成人AV在线电影 | 91成人 片 | 精品国产丝袜白色高跟鞋 | 精品福利一区二区三区 | 午夜成人黄色片 |