JavaScript の遅延読み込み属性パターンに関する簡単な説明

JavaScript の遅延読み込み属性パターンに関する簡単な説明

1. はじめに

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

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

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

2. オンデマンド属性モード

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

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

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

3. 乱雑な遅延読み込み属性パターン

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

クラス 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")); // 偽
 
定数データ = オブジェクト.データ;
console.log(object.hasOwnProperty("data")); // 真

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

4. クラス唯一の遅延読み込み属性モード

遅延ロードされたプロパティが常にインスタンス内に存在することが重要であるユースケースがある場合は、 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")); // 真
 
定数データ = オブジェクト.データ;
console.log(object.hasOwnProperty("data")); // 真

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

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

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

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

VI. 結論

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

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

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

以下もご興味があるかもしれません:
  • js で遅延読み込みを実装するいくつかの方法の詳細な説明
  • JS 同期、非同期、遅延読み込みメソッド
  • js 画像読み込み効果のサンプルコード (遅延読み込み + ウォーターフォール読み込み)
  • js で遅延読み込みを実装するいくつかの方法
  • js 画像の遅延読み込みを実装する 3 つの方法
  • JS を使用して画像の遅延読み込みとフェードイン/フェードアウト効果を実装する簡単な方法
  • ECHO.js 純粋な JavaScript 軽量遅延読み込みサンプルコード
  • JavaScript 画像の遅延読み込みライブラリ Echo.js
  • JQuery の画像遅延読み込みプラグイン jquery.lazyload.js の使い方
  • jQuery プラグイン lazyload.js を使用して画像の読み込みを遅らせる方法

<<:  グループ化されたクエリでのGROUP BYの使用とSQL実行順序の説明

>>:  Ubuntu 19でdockerソースをインストールできない問題を共有する

推薦する

Linuxでmysqlの定期的なコールドバックアップを実装するためにmysqldump+expect+crontabを使用するアイデアの詳細な説明

目次1. 遭遇した問題2. アイデア3. コード1. 遭遇した問題私たちは皆、mysqldump を...

HTML フォーム送信アクションと URL ジャンプアクションの違い

フォームのアクションは URL ジャンプとは異なります。フォームはバックグラウンドにデータを渡すこと...

Vue ライフサイクルの紹介とフック関数の詳細な説明

目次Vueライフサイクルの紹介とフック機能VUEライフサイクルフックVue ライフサイクルの紹介作成...

Windows10のマウスを模倣して境界線を光らせる効果を実現するCSSの詳細解説

最新の Windows 10 アップデートをインストールした後、システム UI の詳細な効果が顕著に...

シェルでパスワードなしでMySQLデータベースに素早くログインする方法

背景Shell の mysql-client を介して MySQL データベースにログインする場合、...

超大型フォントを使用した 40 の Web ページ デザイン

今日の Web デザインでは、非常に大きなフォントが表示される傾向があります。これらのオープンソース...

HTML マルチメディア アプリケーション: Web ページにフラッシュ アニメーションと音楽を挿入する

1. HTML_falshアニメーションでのマルチメディアの応用(WebページへのFlashアニメー...

CSS により、子コンテナが親要素を超えます (子コンテナは親コンテナ内で浮動します)

序文場合によっては、次の図のような浮動効果の要件が必要になります。 成し遂げる標準的な通常の状況では...

mysqlはコンマに基づいてデータ行を複数の行に分割します

目次分離効果コマンドラインの説明関与する機能分離効果-- 別居前1,2,3,4 -- 別居後1 2 ...

オブジェクト指向の観点から Vue コンポーネントを理解するための簡単な分析

同じ関数や HTML コードが複数回使用される場合は、それらをコンポーネントに抽出することを検討でき...

パゴダパネルとドッカーを使用して Gogs をインストールするプロセス全体

目次1 Baota Software StoreにDockerをインストールする2 ゴグスイメージを...

ウェブサイトデザインの基礎知識:初心者の方はぜひお読みください

今では多くの人がウェブサイト作成に参加していますが、ウェブサイトはどのように作成すればよいのでしょう...

Linux 論理ボリューム管理 (LVM) の使用法の概要

ディスク領域の管理は、システム管理者にとって重要な日常的なタスクです。ディスク領域が使い果たされると...

Vueフロントエンドの効率的な開発のためのレンダリング手順をリストします

v-for ディレクティブリストといえば、ループについても触れなければなりません。v-for 命令は...

CSS3 で背景ぼかしを実現する 3 つの方法 (要約)

1. 通常の背景ぼかしコード: <スタイル> html, 体 { 幅: 100%; 高...