JavaScript の遅延読み込み属性パターンを理解する

JavaScript の遅延読み込み属性パターンを理解する

従来、開発者はインスタンスで必要になる可能性のあるデータに対して JavaScript クラス内にプロパティを作成します。コンストラクターですぐに利用できる小さなデータの場合、これは問題ではありません。ただし、インスタンスで使用できるようになる前にデータを計算する必要がある場合は、その料金を前払いしたくない場合があります。たとえば、次のクラスを考えてみましょう。

クラス MyClass {
    コンストラクタ() {
        this.data = someExpensiveComputation();
    }
}

ここでは、いくつかの高価な計算を実行した結果としてdataプロパティが作成されます。プロパティが使用されるかどうかわからない場合は、事前にその計算を実行するのは効率的ではない可能性があります。幸いなことに、これらのアクションを後回しにする方法はいくつかあります。

オンデマンド属性モード

高価な操作の実行を最適化する最も簡単な方法は、計算を実行する前にデータが必要になるまで待つことです。たとえば、次のように、ゲッター付きのアクセサー プロパティを使用して、オンデマンドで計算を行うことができます。

クラス MyClass {
    データを取得する() {
        someExpensiveComputation() を返します。
    }
}

この場合、誰かがそのdata属性を初めて読み取るまで、コストのかかる計算は行われません。これは改善点です。ただし、 data属性が読み取られるたびに同じ高価な計算が実行されるため、少なくとも計算が 1 回しか実行されなかった前の例よりも状況は悪化します。これは良い解決策ではありませんが、これを基にしてより良い解決策を作り出すことができます。

面倒な遅延読み込みプロパティパターン

プロパティにアクセスしたときにのみ計算を実行するのが良いスタートです。本当に必要なのは、その時点以降の情報をキャッシュし、キャッシュされたバージョンのみを使用することです。しかし、この情報を簡単にアクセスできるようにキャッシュする場所はどこでしょうか?これを行う最も簡単な方法は、次のように、同じ名前のプロパティを定義し、その値を計算されたデータに設定することです。

クラス MyClass {
    データを取得する() {
        実際のデータ = someExpensiveComputation();
 
        Object.defineProperty(this, "データ", {
            値: 実際のデータ、
            書き込み可能: false、
            設定可能: false、
            列挙可能: false
        });
 
        実際のデータを返します。
    }
}

ここで、 dataプロパティはクラスのゲッターとして再度定義されますが、今回は結果がキャッシュされます。 Object.defineProperty()を呼び出すと、 actualDataという固定値を持ち、書き込み不可、構成可能、および列挙不可 (ゲッターと一致するように) に設定されたdataという新しいプロパティが作成されます。その後、値自体が返されます。次にdataプロパティにアクセスするときは、ゲッターを呼び出す代わりに、新しく作成されたプロパティから読み取ります。

const オブジェクト = 新しい MyClass();
 
// ゲッターを呼び出す
定数 data1 = オブジェクト.data;
 
// データプロパティから読み取ります
オブジェクトのデータを返します。

実際、すべての計算はdata属性が最初に読み取られたときにのみ実行されます。 dataプロパティのその後の各読み取りでは、キャッシュされたバージョンが返されます。

このパターンの欠点の 1 つは、 dataプロパティが列挙不可能なプロトタイプ プロパティとして始まり、列挙不可能な独自のプロパティとして終了することです。

const オブジェクト = 新しい MyClass();
console.log(object.hasOwnProperty("data")); // 偽
 
const データ = オブジェクト.データ;
console.log(object.hasOwnProperty("data")); // 真

この区別は多くの場合重要ではありませんが、オブジェクトを渡すときに微妙な問題が発生する可能性があるため、このパターンを理解することが重要です。幸いなことに、この問題は更新されたモデルを使用すれば簡単に修正できます。

クラスのプロパティを遅延読み込みするパターン

遅延ロードされたプロパティが常にインスタンス内に存在することが重要であるユースケースがある場合は、 Object.defineProperty()を使用してクラス コンストラクターでプロパティを作成できます。前の例よりも少し複雑ですが、プロパティがインスタンスにのみ存在するようになります。次に例を示します。

クラス MyClass {
    コンストラクタ() {

        Object.defineProperty(this, "データ", {
            得る() {
                実際のデータ = someExpensiveComputation();

                Object.defineProperty(this, "データ", {
                    値: 実際のデータ、
                    書き込み可能: false、
                    設定可能: false
                });

                実際のデータを返します。
            },
            設定可能: true、
            列挙可能: true
        });

    }
}

ここで、コンストラクターdata Object.defineProperty()を使用します。プロパティはインスタンス上に作成され ( thisを使用して)、ゲッターを定義し、プロパティが列挙可能で構成可能であることを指定します (独自のプロパティの典型)。 Object.defineProperty()を再度呼び出せるように、 dataプロパティを構成可能にすることが特に重要です。

次に、ゲッター関数は計算を実行し、 Object.defineProperty()を再度呼び出します。 data属性は、特定の値を持つデータ属性として再定義され、最終データを保護するために書き込み不可および構成不可になりました。計算されたデータはゲッターから返されます。次にdataプロパティが読み取られるときには、保存された値が読み取られます。ボーナスとして、 dataプロパティは独自のプロパティとしてのみ存在するようになり、最初の読み取りの前後で同じように動作します。

const オブジェクト = 新しい MyClass();
console.log(object.hasOwnProperty("data")); // 真
 
const データ = オブジェクト.データ;
console.log(object.hasOwnProperty("data")); // 真

クラスの場合、これがおそらく使用するパターンです。一方、オブジェクト リテラルを使用すると、より簡単なアプローチが可能になります。

オブジェクトリテラルの遅延読み込みプロパティパターン

クラスの代わりにオブジェクト リテラルを使用する場合、オブジェクト リテラルで定義されたゲッターは、データ プロパティと同様に、列挙可能な独自のプロパティ (プロトタイプ プロパティではなく) として定義されるため、プロセスははるかに簡単になります。つまり、オブジェクトに対して煩雑な遅延ロード プロパティ パターンを使用せずに、クラスに対して煩雑な遅延ロード プロパティ パターンを使用できるということです。

定数オブジェクト = {
    データを取得する() {
        実際のデータ = someExpensiveComputation();
 
        Object.defineProperty(this, "データ", {
            値: 実際のデータ、
            書き込み可能: false、
            設定可能: false、
            列挙可能: false
        });
 
        実際のデータを返します。
    }
};
 
console.log(object.hasOwnProperty("data")); // 真
 
const データ = オブジェクト.データ;
console.log(object.hasOwnProperty("data")); // 真

結論は

JavaScript でオブジェクト プロパティを再定義する機能は、計算コストが高くなる可能性のある情報をキャッシュする独自の機会を提供します。アクセサー プロパティをデータ プロパティとして再定義して開始すると、プロパティが最初に読み取られるまで計算を延期し、結果をキャッシュして後で使用することが可能になります。このアプローチはクラスとオブジェクト リテラルの両方で機能し、ゲッターがプロトタイプに配置されるかどうかを心配する必要がないため、オブジェクト リテラルでは少し簡単になります。

パフォーマンスを向上させる最善の方法の 1 つは、同じ作業を繰り返し実行しないようにすることです。そのため、結果を後で使用するためにキャッシュできるときはいつでも、プログラムを高速化できます。遅延読み込みプロパティ パターンなどの手法を使用すると、任意のプロパティをキャッシュ レイヤーにしてパフォーマンスを向上させることができます。

上記は、JavaScript の遅延読み込み属性モードの詳細です。js の遅延読み込み属性の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • js で遅延読み込みを実装するいくつかの方法の詳細な説明
  • JS 同期、非同期、遅延読み込みメソッド
  • JS を使用してファースト スクリーン以外の画像の遅延読み込みを実装する例
  • 複数の画像の遅延読み込み効果を実現する js
  • js で遅延読み込みを実装するいくつかの方法

<<:  10分でDockerを使ったマイクロサービスのデプロイ方法を学ぶ

>>:  更新とデータ整合性処理のためのMySQLトランザクション選択の説明

推薦する

進捗バーのネイティブ JavaScript 実装

進捗バーを実装するためのJavaScriptの具体的なコードは参考までに。具体的な内容は次のとおりで...

CentOS7 で MySQL 5.7.24 をコンパイルしてインストールする詳細なチュートリアル

目次依存関係をインストールするブーストをインストールMySQLをコンパイルしてインストールする構成依...

JavaScript データのフラット化の詳細な説明

目次フラット化とは何か再帰トストリング減らすアンダーコア_.平坦化_。連合_。違い要約するフラット化...

Vue+SSMは画像アップロードのプレビュー効果を実現します

現在の要件は、ファイルのアップロード ボタンがあることです。ボタンをクリックすると、アップロードする...

LinuxカーネルマクロContainer_Ofの詳細な説明

目次1. 構造体はメモリにどのように保存されますか? 2. container_ofマクロ3. 型4...

HTML 5 スタイルシートのリセット

この CSS リセットは、Eric Meyers の CSS リセットに基づいて変更されており、特に...

Vueフォームバインディングとコンポーネントの詳細な説明

目次1. 双方向データバインディングとは1. データの双方向バインディングを実装する必要があるのはな...

HTML でフォーム入力やその他のテキスト ボックスを読み取り専用にして編集不可にする方法

場合によっては、フォーム内のテキスト ボックスを読み取り専用にして、ユーザーがその中の情報を変更でき...

CSS3 のカラー値 RGBA とグラデーションカラーの使用方法の紹介

CSS3以前は、グラデーション画像は背景画像としてのみ使用できました。 CSS3 のグラデーション構...

MLSQL スタックでストリームのデバッグを簡単にする方法

序文クラスメートが MLSQL Stack のストリーミング サポートを調査しています。そこで、フロ...

Nginx の一般的な設定とテクニックの概要

序文この記事では、Nginx の一般的な、実用的で興味深い構成をいくつか紹介します。この記事を読んだ...

Linux crontab コマンドの使用

1. コマンドの紹介contab (cron テーブル) コマンドは、Windows のスケジュール...

jsはショッピングカートの加算と減算、価格計算を実装します

この記事の例では、ショッピングカートの加算と減算、価格計算を実装するためのjsの具体的なコードを共有...

集める価値のある 15 個の JavaScript 関数

目次1. 数字を逆にする2. 配列内の最大のn個の数値を取得する3. 階乗を計算する4. 現在の動作...