JSON.stringify の簡易版の実装とその 6 つの主要機能の詳細な説明

JSON.stringify の簡易版の実装とその 6 つの主要機能の詳細な説明

序文

JSON.stringify は非常に頻繁に使用される API ですが、コード プログラムに地雷を埋め込まないように、使用中に注意する必要がある機能があります。そこで、jsonStringify 関数の簡単なバージョンを一緒に実装してみましょう。

JSON.stringify の 6 つの機能

特集1

ブール値、数値、文字列のラップされたオブジェクトは、シリアル化時に自動的に対応する元の値に変換されます。

現在、次のようなオブジェクトがあります。

定数オブジェクト = {
    bol: 新しいブール値(true)、
    num: 新しい数値(1)、
    str: 新しい文字列(1)
}

typeofを使用してobjの各属性のデータ型を検出します。

typeof obj.bol; // オブジェクト
typeof obj.num; // オブジェクト
typeof obj.str; // オブジェクト

連載後

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

この時点で、解析して各属性のデータ型を見つけます。

JSON を解析して文字列を解析する
typeof stringifyObj.bol; // ブール値
typeof stringifyObj.num; // 数値
typeof stringifyObj.str; // 文字列

特集2

NaN、Infinity、-Infinity、nullはすべて文字列化中にnullとして扱われます。

定数オブジェクト = {
    ナン: NaN、
    無限: 無限、
    ヌル: ヌル、
};

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

特集3

オブジェクトがシリアル化されるときに、toJSON 関数がある場合、この関数によって返される値は、オブジェクト全体のシリアル化の結果になります。

定数オブジェクト = {
    ナン: NaN、
    無限: 無限、
    ヌル: ヌル、
    JSON() {
        「toJSON関数があります」を返します。
    },
};

JSON.stringify(obj); // "toJSON関数があります"

シリアル化後は、toJSON 関数の戻り値のみが存在し、残りのデータは無視されることがわかります。

⚠️: toJSON 関数が Date にデプロイされているため、日付データは通常どおりシリアル化されます。これは、コンソールで Date.prototype.toJSON を出力することで確認できます。

定数オブジェクト = {
    日付: 新しい Date(),
};

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

特集4

未定義、関数、シンボルは異なる動作をする

オブジェクトのキーと値のペアとして:

値として:

定数オブジェクト = {
    未定義: 未定義、
    関数fn() {},
    シンボル: シンボル()
};

JSON.stringify(obj); // {}

キーとして:

定数fn = 関数(){};
定数オブジェクト = {
    [未定義]: 未定義、
    [関数]: 関数() {},
    [シンボル()]: シンボル()
};

JSON.stringify(obj); // {}

undefined、function、および symbol がオブジェクトのキーと値として使用されている場合、それらはシリアル化中に無視されます。

⚠️: 上記の 3 種類のデータはシリアル化中に無視されるため、オブジェクトの元の順序が変わる可能性があります。

配列値として:

const arr = [未定義、関数fn() {}、シンボル()];

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

undefined、function、および symbol が配列値として使用された場合、それらはすべてシリアル化中に null に変換されます。

一人でいるとき:

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

undefined、function、および symbol が単独で存在する場合、シリアル化中にそれらはすべて undefined に変換されます。

特集5

シリアル化中は、列挙可能なプロパティのみがシリアル化され、列挙不可能なプロパティは無視されます。

定数オブジェクト = {
    名前: "nordon",
    年齢: 18歳
};

// 年齢を列挙不可能なプロパティに変更する Object.defineProperty(obj, "age", {
    列挙可能: false、
});

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

⚠️: これにより、オブジェクトの元の順序も変更されます

特集6

循環参照されたオブジェクトはシリアル化中に例外をスローします

定数オブジェクト = {
    名前: "nordon",
    年齢: 18歳
};

定数p = {
    名前: 'wy',
    オブジェクト
}

オブジェクトp = p

JSON.stringify(obj);

これにより、コンソールに例外がスローされます。

キャッチされない TypeError: 循環構造を JSON に変換しています --> コンストラクター 'Object' を持つオブジェクトから開始 | プロパティ 'p' -> コンストラクター 'Object' を持つオブジェクト --- プロパティ 'obj' は JSON.stringify (<anonymous>) で循環を閉じます

手動で文字列化を実装する

JSON.stringify の機能のいくつかを理解したので、これらの機能に基づいて kack バージョンを実装できます。

実装する前に、カリー化を使用して、データ型検証用のいくつかのツール関数をカプセル化します。

const カリー化 = (fn, ...outParams) => {
    // fn 関数に必要なパラメータの数を取得します。const paramsLen = fn.length;

    戻り値 (...引数) => {
        // すべてのパラメータを収集します。let params = [...outParams, ...args];
        // パラメータがfnに必要なパラメータに達しない場合は、パラメータの収集を続けます。if (params.length < paramsLen) {
            カリー化(fn, ...params)を返します。
        }

        fn(...params) を返します。
    };
};

/**
 * type: タイプ - [オブジェクト配列]、[オブジェクト番号]など。 * source: データソース */
const judgeType = (type, source) => {
    Object.prototype.toString.call(source) === type を返します。
};

const isUndefined = currying(judgeType, "[オブジェクト Undefined]");
const isSymbol = currying(judgeType, "[オブジェクト シンボル]");
const isFunction = currying(judgeType, "[オブジェクト Function]");
const isObject = currying(judgeType, "[object Object]");
const isNull = currying(judgeType, "[オブジェクト Null]");

直接的なコードは次のとおりです:

関数jsonStringify(データ) {
    type = typeofデータとします。

    if (isNull(データ)) { 
// null は直接文字列 'null' を返します
        「null」を返します。
    } そうでない場合 (data.toJSON && typeof data.toJSON === "function") {
// toJSON 関数を設定し、toJSON によって返されたデータを直接使用し、他のデータは無視します return jsonStringify(data.toJSON());
    } そうでない場合 (Array.isArray(data)) {
        結果 = [] とします。
        //配列の場合、配列内の各項目は異なる型である可能性があります data.forEach((item, index) => {
            if (isUndefined(item) || isSymbol(item) || isFunction(item)) {
                結果[インデックス] = "null";
            } それ以外 {
                結果[インデックス] = jsonStringify(item);
            }
        });

        結果 = "[" + 結果 + "]";

        結果を返します。replace(/'/g, '"');
    } そうでない場合 (isObject(データ)) {
        // 通常のオブジェクトを処理する let result = [];
        Object.keys(data).forEach((item, index) => {
            if (typeof item !== "シンボル") {
                //キーがシンボルオブジェクトの場合、if(を無視する
                    データ[項目] !== 未定義 &&
                    typeof data[item] !== "function" &&
                    typeof data[item] !== "symbol"
                ){
                    //キー値が未定義、関数、またはシンボルの場合は無視します。result.push(
                        '"' + 項目 + '"' + ":" + jsonStringify(data[item])
                    );
                }
            }
        });

        戻り値: ("{" + 結果 + "}").replace(/'/g, '"');
    } そうでない場合 (type !== "object") {
        結果 = データとします。

        //data は基本データ型である可能性があるので、ここで処理します if (Number.isNaN(data) || data === Infinity) {
            //NaN および Infinity のシリアル化は「null」を返します
            結果 = "null";
        } そうでない場合 (isUndefined(データ) || isSymbol(データ) || isFunction(データ)) {
            // 関数のシリアル化は undefined を返すため、undefined およびシンボル return undefined と一緒に処理されます。
        } そうでない場合 (type === "文字列") {
            結果 = '"' + データ + '"';
        }

        String(結果)を返します。
    }
}

この時点で、JSON.stringify の簡易版は完成しました。まだ多くの機能が欠けていますが、主にアイデアを提供しています。コアコメントはコード内に注釈が付けられており、コードと上記の機能と一緒に理解できます。

要約する

JSON.stringify の実装とその 6 つの主要機能に関するこの記事はこれで終わりです。JSON.stringify のより簡略化されたバージョンとその機能については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JSON.stringify() の 5 つの秘密の機能の説明
  • JSON オブジェクトと文字列間の変換について説明します。JSON.stringify(obj) と JSON.parse(string)
  • JSON.stringifyがJSONを変換するときに日付と時刻が不正確になる問題の解決方法
  • JSON.stringify の 9 つの機能と変換ルールを学ぶ

<<:  W3C が推奨するモバイル Web マークアップ言語 XHTML Basic 1.1

>>:  非常に詳細な MySQL8.0.22 のインストールと設定のチュートリアル

推薦する

Reactでレシピシステムを実装する方法を解説した記事

目次1. レシピ集1.1 プロジェクトの背景1.2 テクノロジースタック1.3 開発環境1.4. プ...

MySQL シリーズ 8 MySQL サーバー変数

チュートリアルシリーズMySQL シリーズ: MySQL リレーショナル データベースの基本概念My...

JS での Reduce() メソッドの使用の概要

目次1. 文法2. 例3. その他の関連方法長い間、reduce() メソッドの具体的な使い方を理解...

CSSトランジションは高さを変更することで要素を拡大したり縮小したりします。

一般的な開発ニーズとして、要素の一部を必要になるまで折りたたんでおきたいことが挙げられます。 Boo...

nginx 設定ファイルパスとリソースファイルパスを表示する方法

nginx 設定ファイルのパスを表示する nginx -t 経由nginx -t コマンドの本来の機...

Reactは無限ループスクロール情報を実装する

この記事では、無限ループスクロールを実現するためのReactの具体的なコードを参考までに紹介します。...

JS 手ぶれ補正機能の実装と使用シナリオ

目次1. 手ぶれ補正機能とは何ですか? 1. なぜ手ぶれ補正機能が必要なのでしょうか? 2. 手ぶれ...

MySQL B-Tree インデックスの簡単な分析

Bツリーインデックス異なるストレージ エンジンでは、異なるストレージ構造を使用する場合もあります。た...

元のPATHを上書きしてコマンドが見つからないというメッセージが表示されるコマンド失敗の問題を解決する方法

同僚から、LINUX サーバー上の多くのコマンドが (コマンドが見つかりません) というプロンプトで...

echarts と vue.js を統合する際に発生するいくつかの問題の概要

序文現在、私は Beetlex のデータ分析プラットフォームに取り組んでいます。この製品の開発では、...

IdeaでTomcatを起動したときに複数のリスナーが報告される問題を解決する

エラーのスクリーンショット例外が発生した場所が見つかりません。解決策: リソースディレクトリにlog...

jsはユーザーのページ操作を記憶するためにクッキーを使用します

序文開発プロセスでは、ブラウザレベルでユーザーが実行した操作を記憶するなど、同様の要件に遭遇すること...

Vue.jsフレームワークはショッピングカート機能を実装します

この記事では、ショッピングカートを実装するためのVue.jsフレームワークの具体的なコードを参考まで...

リンク内の href=# はどういう意味ですか?

現在のページへのリンク。 -------------------一般的な使用法は次のとおりです。 &...