您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何實(shí)現(xiàn)簡(jiǎn)易版本JSON.stringify”,在日常操作中,相信很多人在如何實(shí)現(xiàn)簡(jiǎn)易版本JSON.stringify問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何實(shí)現(xiàn)簡(jiǎn)易版本JSON.stringify”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
前言
JSON.stringify六大特性
特性一
特性二
特性三
特性四
特性五
特性六
手動(dòng)實(shí)現(xiàn)stringify
JSON.stringify是一個(gè)使用非常高頻的API,但是其卻存在一個(gè)特性,我們?cè)谑褂玫倪^(guò)程中需要留意這些特性以避免為代碼程序埋雷
布爾值、數(shù)字、字符串的包裝對(duì)象在序列化過(guò)程中會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值
現(xiàn)在有這么一個(gè)對(duì)象:
const obj = { bol: new Boolean(true), num: new Number(1), str: new String(1) }
利用typeof檢測(cè)obj各個(gè)屬性的數(shù)據(jù)類型
typeof obj.bol; // object typeof obj.num; // object typeof obj.str; // object
將其序列化stringify之后
JSON.stringify(obj); // {"bol":true,"num":1,"str":"1"}
此時(shí)再將其解析parse進(jìn)行各個(gè)屬性的數(shù)據(jù)類型
const stringifyObj = JSON.parse(JSON.stringify(obj)); typeof stringifyObj.bol; // boolean typeof stringifyObj.num; // number typeof stringifyObj.str; // string
NaN、Infinity、-Infinity以及null在序列化stringify時(shí)都會(huì)被當(dāng)作null
const obj = { nan: NaN, infinity: Infinity, null: null, }; JSON.stringify(obj); // {"nan":null,"infinity":null,"null":null}
對(duì)象在序列化的時(shí)候,若是其存在toJSON函數(shù),這個(gè)函數(shù)返回的值就是整個(gè)對(duì)象序列化后的結(jié)果
const obj = { nan: NaN, infinity: Infinity, null: null, toJSON() { return "擁有toJSON函數(shù)"; }, }; JSON.stringify(obj); // "擁有toJSON函數(shù)"
可以看到序列化之后的數(shù)據(jù)僅存在toJSON函數(shù)的返回值,其余數(shù)據(jù)全部忽略
??:Date數(shù)據(jù)會(huì)被正常序列化,因?yàn)镈ate上部署了toJSON函數(shù),可以通過(guò)控制臺(tái)打印Date.prototype.toJSON得知
const obj = { date: new Date(), }; JSON.stringify(obj); // {"date":"2021-10-08T11:43:31.881Z"}
表現(xiàn)不一的undefined、function和symbol
作為對(duì)象鍵值對(duì)時(shí):
作為值:
const obj = { undefined: undefined, fn() {}, symbol: Symbol() }; JSON.stringify(obj); // {}
作為鍵:
const fn = function () {}; const obj = { [undefined]: undefined, [fn]: function () {}, [Symbol()]: Symbol() }; JSON.stringify(obj); // {}
undefined、function和symbol作為對(duì)象的key和value時(shí),會(huì)在序列化時(shí)將其忽略
??:此時(shí)可能會(huì)改變對(duì)象原有的順序,因?yàn)樯鲜鋈N數(shù)據(jù)會(huì)在序列化時(shí)被忽略
作為數(shù)組值時(shí):
const arr = [undefined, function fn() {}, Symbol()]; JSON.stringify(arr); // [null,null,null]
undefined、function和symbol作為數(shù)組的value時(shí),會(huì)在序列化時(shí)將其都轉(zhuǎn)換為null
單獨(dú)存在時(shí):
JSON.stringify(undefined); // undefined JSON.stringify(function () {}); // undefined JSON.stringify(Symbol()); // undefined
undefined、function和symbol單獨(dú)存在時(shí),會(huì)在序列化時(shí)都轉(zhuǎn)換為undefined
序列化過(guò)程中,僅會(huì)序列化可枚舉屬性,不可枚舉屬性將會(huì)忽視
const obj = { name: "nordon", age: 18, }; // 將age修改為不可枚舉屬性 Object.defineProperty(obj, "age", { enumerable: false, }); JSON.stringify(obj); // {"name":"nordon"}
??:此舉也會(huì)改變對(duì)象的原有順序
循環(huán)引用的對(duì)象,會(huì)在序列化時(shí)拋出異常
const obj = { name: "nordon", age: 18, }; const p = { name: 'wy', obj } obj.p = p JSON.stringify(obj);
此時(shí)會(huì)導(dǎo)致控制臺(tái)拋出異常:
Uncaught TypeError: Converting circular structure to JSON --> starting at object with constructor 'Object' | property 'p' -> object with constructor 'Object' --- property 'obj' closes the circle at JSON.stringify (<anonymous>)
明白了JSON.stringify的一些特性,接下來(lái)便可以依據(jù)這些特性動(dòng)手實(shí)現(xiàn)一個(gè)kack版本
在動(dòng)手實(shí)現(xiàn)之前,先利用柯里化封裝一些數(shù)據(jù)類型校驗(yàn)的工具函數(shù):
const currying = (fn, ...outParams) => { // 獲取 fn 函數(shù)需要的參數(shù)個(gè)數(shù) const paramsLen = fn.length; return (...args) => { // 收集全部參數(shù) let params = [...outParams, ...args]; // 若參數(shù)沒(méi)有達(dá)到 fn 需要的參數(shù),繼續(xù)收集參數(shù) if (params.length < paramsLen) { return currying(fn, ...params); } return fn(...params); }; }; /** * type: 類型 - [object Array]、[object Number]等 * source: 數(shù)據(jù)源 */ const judgeType = (type, source) => { return Object.prototype.toString.call(source) === type; }; const isUndefined = currying(judgeType, "[object Undefined]"); const isSymbol = currying(judgeType, "[object Symbol]"); const isFunction = currying(judgeType, "[object Function]"); const isObject = currying(judgeType, "[object Object]"); const isNull = currying(judgeType, "[object Null]");
下面直接上代碼:
function jsonStringify(data) { let type = typeof data; if (isNull(data)) { // null 直接返回 字符串'null' return "null"; } else if (data.toJSON && typeof data.toJSON === "function") { // 配置了 toJSON函數(shù), 直接使用 toJSON 返回的數(shù)據(jù)且忽略其他數(shù)據(jù) return jsonStringify(data.toJSON()); } else if (Array.isArray(data)) { let result = []; //如果是數(shù)組,那么數(shù)組里面的每一項(xiàng)類型又有可能是多樣的 data.forEach((item, index) => { if (isUndefined(item) || isSymbol(item) || isFunction(item)) { result[index] = "null"; } else { result[index] = jsonStringify(item); } }); result = "[" + result + "]"; return result.replace(/'/g, '"'); } else if (isObject(data)) { // 處理普通對(duì)象 let result = []; Object.keys(data).forEach((item, index) => { if (typeof item !== "symbol") { //key 如果是 symbol 對(duì)象,忽略 if ( data[item] !== undefined && typeof data[item] !== "function" && typeof data[item] !== "symbol" ) { //鍵值如果是 undefined、function、symbol 為屬性值,忽略 result.push( '"' + item + '"' + ":" + jsonStringify(data[item]) ); } } }); return ("{" + result + "}").replace(/'/g, '"'); } else if (type !== "object") { let result = data; //data 可能是基礎(chǔ)數(shù)據(jù)類型的情況在這里處理 if (Number.isNaN(data) || data === Infinity) { //NaN 和 Infinity 序列化返回 "null" result = "null"; } else if (isUndefined(data) || isSymbol(data) || isFunction(data)) { // 由于 function 序列化返回 undefined,因此和 undefined、symbol 一起處理 return undefined; } else if (type === "string") { result = '"' + data + '"'; } return String(result); } }
到此,關(guān)于“如何實(shí)現(xiàn)簡(jiǎn)易版本JSON.stringify”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。