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 のインストールと設定のチュートリアル

推薦する

Websocket に基づくシンプルなチャットルームダイアログの実装

この記事では、WebSocketを使用して簡単なチャットルームの会話を実装するための具体的なコードを...

Docker マルチステージビルドを使用してイメージサイズを縮小する方法

この記事では、Docker のマルチステージ ビルド機能を使用してイメージ サイズを大幅に削減する方...

同じページを動的にロードするための Vue ルーティングリスニングの例

目次シナリオ分析発達要約するシナリオ分析システムでは、1 つのモジュールに 3 つのサブモジュールが...

Linux システムでの virtuoso データベースの詳細なインストールと使用

最近、リンク データについていくつか調査していて、rdf データベースを使用する必要があったため、v...

MySQL 中断された接続警告ログの分析

序文:場合によっては、MySQL に接続されたセッションが異常終了することが多く、エラー ログに「通...

Dockerイメージをインポートおよびエクスポートする方法

この記事では、移行、バックアップ、アップグレードなどのシナリオで使用される Docker イメージの...

HTML テーブル タグ チュートリアル (34): 行スパン属性 ROWSPAN

複雑なテーブル構造では、一部のセルが水平方向に複数のセルにまたがるため、行間属性 ROWSPAN を...

内部 IP アクセスのみを許可する Nginx プロキシ設定を追加する方法

位置 / { インデックス index.jsp; proxy_next_upstream http...

JavaScript のクロージャによって発生する問題を回避する

閉鎖による問題を回避するためのletについてオブジェクト指向の考え方を使用して、購入者情報の削除機能...

jQuery で呼吸カルーセル効果を実現

この記事では、呼吸カルーセル効果を実現するためのjQueryの具体的なコードを参考までに共有します。...

MySQLとElasticsearch間のデータ非対称性問題の解決策

MySQLとElasticsearch間のデータ非対称性問題の解決策jdbc-input-plugi...

Centos7 ベースの Nginx Web サイト サーバーの構築の詳細説明 (仮想 Web ホストの構成を含む)

1. Nginx サービス基盤Nginx (エンジン x) は、パフォーマンスの最適化のために特別...

MySQL 5.7.27 のダウンロード、インストール、設定に関する詳細なチュートリアル

目次1. ダウンロード手順2. 環境変数を設定する3. my.iniファイルを設定する4. MySQ...

Node.js コード実行をバイパスするためのヒントのまとめ

目次1. 子プロセス2. nodejsでのコマンド実行2.1 16進数エンコード2.2 ユニコードエ...

CSS グリッドレイアウトで列にアイテムを埋め込む方法

n 個のアイテムがあり、これらのアイテムをグリッド レイアウトの列に並べ替える必要があるとします。列...