中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現簡易版本JSON.stringify

發布時間:2021-10-12 10:06:31 來源:億速云 閱讀:107 作者:iii 欄目:開發技術

這篇文章主要介紹“如何實現簡易版本JSON.stringify”,在日常操作中,相信很多人在如何實現簡易版本JSON.stringify問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何實現簡易版本JSON.stringify”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

目錄
  • 前言

  • JSON.stringify六大特性

    • 特性一

    • 特性二

    • 特性三

    • 特性四

    • 特性五

    • 特性六

  • 手動實現stringify

前言

JSON.stringify是一個使用非常高頻的API,但是其卻存在一個特性,我們在使用的過程中需要留意這些特性以避免為代碼程序埋雷

JSON.stringify六大特性

特性一

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

現在有這么一個對象:

const obj = {
    bol: new Boolean(true),
    num: new Number(1),
    str: new String(1)
}

利用typeof檢測obj各個屬性的數據類型

typeof obj.bol; // object
typeof obj.num; // object
typeof obj.str; // object

將其序列化stringify之后

JSON.stringify(obj); // {"bol":true,"num":1,"str":"1"}

此時再將其解析parse進行各個屬性的數據類型

const stringifyObj = JSON.parse(JSON.stringify(obj));
typeof stringifyObj.bol; // boolean
typeof stringifyObj.num; // number
typeof stringifyObj.str; // string

特性二

NaN、Infinity、-Infinity以及null在序列化stringify時都會被當作null

const obj = {
    nan: NaN,
    infinity: Infinity,
    null: null,
};

JSON.stringify(obj); // {"nan":null,"infinity":null,"null":null}

特性三

對象在序列化的時候,若是其存在toJSON函數,這個函數返回的值就是整個對象序列化后的結果

const obj = {
    nan: NaN,
    infinity: Infinity,
    null: null,
    toJSON() {
        return "擁有toJSON函數";
    },
};

JSON.stringify(obj); // "擁有toJSON函數"

可以看到序列化之后的數據僅存在toJSON函數的返回值,其余數據全部忽略

??:Date數據會被正常序列化,因為Date上部署了toJSON函數,可以通過控制臺打印Date.prototype.toJSON得知

const obj = {
    date: new Date(),
};

JSON.stringify(obj); // {"date":"2021-10-08T11:43:31.881Z"}

特性四

表現不一的undefined、function和symbol

作為對象鍵值對時:

作為值:

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作為對象的key和value時,會在序列化時將其忽略

??:此時可能會改變對象原有的順序,因為上述三種數據會在序列化時被忽略

作為數組值時:

const arr = [undefined, function fn() {}, Symbol()];

JSON.stringify(arr); // [null,null,null]

undefined、function和symbol作為數組的value時,會在序列化時將其都轉換為null

單獨存在時:

JSON.stringify(undefined); // undefined
JSON.stringify(function () {}); // undefined
JSON.stringify(Symbol()); // undefined

undefined、function和symbol單獨存在時,會在序列化時都轉換為undefined

特性五

序列化過程中,僅會序列化可枚舉屬性,不可枚舉屬性將會忽視

const obj = {
    name: "nordon",
    age: 18,
};

// 將age修改為不可枚舉屬性
Object.defineProperty(obj, "age", {
    enumerable: false,
});

JSON.stringify(obj); // {"name":"nordon"}

??:此舉也會改變對象的原有順序

特性六

循環引用的對象,會在序列化時拋出異常

const obj = {
    name: "nordon",
    age: 18,
};

const p = {
    name: 'wy',
    obj
}

obj.p = p

JSON.stringify(obj);

此時會導致控制臺拋出異常:

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>)

手動實現stringify

明白了JSON.stringify的一些特性,接下來便可以依據這些特性動手實現一個kack版本

在動手實現之前,先利用柯里化封裝一些數據類型校驗的工具函數:

const currying = (fn, ...outParams) => {
    // 獲取 fn 函數需要的參數個數
    const paramsLen = fn.length;

    return (...args) => {
        // 收集全部參數
        let params = [...outParams, ...args];
        // 若參數沒有達到 fn 需要的參數,繼續收集參數
        if (params.length < paramsLen) {
            return currying(fn, ...params);
        }

        return fn(...params);
    };
};

/**
 * type: 類型 - [object Array]、[object Number]等
 * source: 數據源
 */
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函數, 直接使用 toJSON 返回的數據且忽略其他數據
        return jsonStringify(data.toJSON());
    } else if (Array.isArray(data)) {
        let result = [];
        //如果是數組,那么數組里面的每一項類型又有可能是多樣的
        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)) {
        // 處理普通對象
        let result = [];
        Object.keys(data).forEach((item, index) => {
            if (typeof item !== "symbol") {
                //key 如果是 symbol 對象,忽略
                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 可能是基礎數據類型的情況在這里處理
        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);
    }
}

到此,關于“如何實現簡易版本JSON.stringify”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

赣州市| 台东县| 汨罗市| 交城县| 上栗县| 龙口市| 花莲市| 凤山县| 中超| 霞浦县| 乌拉特后旗| 丹凤县| 鲁山县| 吉林省| 古丈县| 西吉县| 黄山市| 连城县| 罗定市| 怀集县| 忻州市| 宣化县| 内丘县| 寿宁县| 桃江县| 资源县| 玉山县| 南京市| 黄骅市| 德昌县| 芦溪县| 门头沟区| 巴林左旗| 弥渡县| 安顺市| 郸城县| 二连浩特市| 铜山县| 阳西县| 民勤县| 盘山县|