私は最近、ECMAScript 5 を最大限に活用する必要があるクライアントとのプロジェクトに取り組んでいたのですが、非常に興味深い問題に遭遇しました。 この問題は、非常に一般的なパターン、つまり JavaScript で 1 つのオブジェクトのプロパティまたはメソッドを別のオブジェクトに混合するミックスインに起因します。
ほとんどのミックスインの機能は次のようになります:
コードをコピー
この例では、オブジェクト object はプロパティ名とメソッドsayName()を受け取ります。 これは ECMAScript 3 では正常に機能しますが、ECMAScript 5 ではあまり機能しません。
これが私が抱えている問題です:
コードをコピー
}
});
// これは後で言っておきます
name = "Nicholas";
}());
この例は少し不自然に見えますが、問題を正確に説明しています。 混合されるプロパティでは、ECMAScript 5 の新機能であるゲッター プロパティ アクセサーが使用されます。ゲッターは初期化されていないローカル変数名を参照しているため、プロパティは未定義です。
その後、アクセサーゲッターが有効な値を返せるように、name に値が割り当てられます。 残念ながら、object.name (mixined プロパティ) は常に未定義を返します。
mixin() 関数を注意深く分析してみましょう。 実際、ループ ステートメントでは、プロパティはあるオブジェクトから別のオブジェクトに再割り当てされません。 実際には、同じ名前のプロパティを作成し、それにサプライヤー オブジェクトのアクセサー メソッド getter の戻り値を割り当てます。 (注釈: ターゲット オブジェクトはゲッター メソッドを取得するのではなく、ゲッター メソッドの戻り値を取得します。@justjavac)
この例では、mixin() プロセスは実際には次のようになります:
コードをコピー
コードをコピーします
この新しいバージョンの関数では、Object.keys() を使用して、サプライヤー オブジェクトのすべての列挙プロパティを含む配列を取得します。 次に、foreach() メソッドを使用して、これらのプロパティを反復処理します。 Object.getOwnPropertyDescriptor() メソッドを呼び出して、サプライヤー オブジェクトの各プロパティ記述子 (記述子) を取得します。
記述子にはゲッター メソッドやセッター メソッドを含むすべてのプロパティ情報が含まれているため、記述子を Object.defineProperty() に直接渡して、受信側オブジェクトに同じプロパティを作成できます。 この新しいバージョンの mixin() を使用すると、以前に発生した問題を解決し、期待どおりの結果を得ることができます。 getter メソッドはサプライヤーからレシーバーに正しく渡されます。
もちろん、古いブラウザをサポートする必要がある場合は、ECMAScript 3 にフォールバックする関数が必要になります。
mixin() 関数を使用する必要がある場合は、ECMAScript 5、特にゲッター メソッドとセッター メソッドで正しく動作することを必ず再確認してください。 そうしないと、私と同じような間違いを犯すことになります。