
私のAtomJSフレームワークでは、アクセッター(ゲッターとセッター)を積極的に使用しています。
Foo = atom.Class({ get bar () { return this._bar; }, set bar (bar) { this._bar = bar; } });
理論についてはすでに説明しましたが、トピックでは、すべての最新のブラウザーでそれらを動作させる方法、つまりInternet Explorer 9が
__defineSetter__
および同様のメソッドについて何も知らないという事実で状況を解決する方法について説明します。
幸いなことに、この点で、すべてのブラウザーはほぼ同じです。 IE9 +、Opera10 +、Fx3.5 +、Chrome-すべてこのエントリをサポートし、動作と構文は同じです。 唯一のものは、Internet Explorer 9がポップアップする場合、「
おそらく ':'
'が
':'
"-ブラウザが「Interner Explorer 7」の
「Bagodrom」モードに切り替わったかどうかを確認することです。
ここで複雑なことはありません
非標準の場合
__defineSetter__
__defineSetter__
および
__defineGetter__
__defineGetter__
は、EcmaScript5-
Object.definePropertyの代替
です 。 デフォルトでは、オブジェクトの
configurable
および
enumerable
プロパティはtrueとして宣言されているため、標準の代替を簡単に記述できます。
instance.__defineSetter__(propertyName, setterFn); instance.__defineGetter__(propertyName, getterFn);
非標準の場合
__lookupSetter__
__lookupSetter__
および
__lookupGetter__
__lookupGetter__
には、EcmaScript5-
Object.getOwnPropertyDescriptorの代替もあります。
すべてが少し喜びではありませんが、重要ではありません。 秘密は、
__lookup*__
はプロトタイプチェーン全体に沿ってアクセサを検索するのに対し、
getOwnPropertyDescriptor
は個人のプロパティでのみ検索することです。
指定されたオブジェクトの独自のプロパティ(つまり、オブジェクトのプロトタイプチェーンに沿って存在するのではなく、オブジェクトに直接存在するプロパティ)のプロパティ記述子を返します。
つまり、
次の状況があり
ます 。
var MyClass = function () {}; MyClass.prototype = { get foo() { return 42; } }; var instance = new MyClass(); console.log(instance.__lookupGetter__('foo'));
ゲッターには実際には次のものがあります:
console.log(instance.foo);
1.非標準プロパティのより正確かつ論理的な動作
2.私のフレームワークのアイデアにより適しています。
3.すべてのブラウザが同じように動作することが重要です。 それほど重要ではない
したがって、
null
、または特定のプロパティまたはアクセサに
到達するまで、
Object.getPrototypeOfメソッドを使用してプロトタイプチェーン全体を再帰的に処理します。
function getPropertyDescriptor (from, key) { var descriptor = Object.getOwnPropertyDescriptor(from, key); if (!descriptor) {
すべてをライブラリに入れる
これで、取得した知識を適用して、ブラウザ間のアクセサー用のライブラリを作成できます。
私の個人的な観察によると、非標準の方法は少し速く動作し、必要なハックも少ないので、デフォルトとして採用しましょう。
また、私は名前の
lookup
と
define
好きです-それらは簡潔で理解しやすいので、私たちはそれらを使用する理由です。
2つの異なる関数を作成するだけで、毎回余分なチェックを行わないため、各メソッドのルックアップ関数の内容は根本的に異なります。
(function (Object) { var standard = !!Object.getOwnPropertyDescriptor, nonStandard = !!{}.__defineGetter__; if (!standard && !nonStandard) throw new Error('Accessors are not supported'); var lookup = nonStandard ? function (from, key) { var g = from.__lookupGetter__(key), s = from.__lookupSetter__(key); return ( g || s ) ? { get: g, set: s } : null; } : function (from, key) { var descriptor = Object.getOwnPropertyDescriptor(from, key); if (!descriptor) { var proto = Object.getPrototypeOf(from); if (proto) return accessors.lookup(proto, key); } else if ( descriptor.set || descriptor.get ) { return { set: descriptor.set, get: descriptor.get }; } return null; }; var define = nonStandard ? function (object, prop, descriptor) { if (descriptor) { if (descriptor.get) object.__defineGetter__(prop, descriptor.get); if (descriptor.set) object.__defineSetter__(prop, descriptor.set); } return object; } : function (object, prop, descriptor) { if (descriptor) { var desc = { get: descriptor.get, set: descriptor.set, configurable: true, enumerable: true }; Object.defineProperty(object, prop, desc); } return object; }; this.accessors = { lookup: lookup, define: define }; })(Object);
これで、オブジェクトで
アクセサーを
宣言できます。
MyClass = function (param) { var property = param; accessors.define(this, 'property', { set: function (value) { property = value; }, get: function () { return property; } }); }; var instance = new MyClass(42); console.log(instance.property);
継承
inherit
メソッドを追加して、ライブラリを少し拡張してみましょう。 これは、fromオブジェクトから
key
という名前のプロパティアクセサーを受け取り、toオブジェクトに追加します。 成功した場合は
true
、そうでない場合は
false
返し
true
。
this.accessors = { lookup: lookup, define: define, inherit: function (from, to, key) { var a = accessors.lookup(from, key); if ( a ) { accessors.define(to, key, a); return true; } return false; } };
このメソッドは、
jQuery.extend
をサポートする
MooTools
jQuery.extend
または
Object.merge
類似物を作成するのに役立ちますが、すべての通常のフレームワークはそれらについて何も知りません。
var object = jQuery.extend({}, { get foo(){ return null; } }); console.log( object.__lookupGetter__('foo') );
独自のバージョンを作成します(注意、このオプションは教育目的で作成されたものであり、実際のアプリケーションでは使用しないでください)
function extend(from, to) { for (var i in to) {
おわりに
とても快適です。 高度に特化された2つの非常に強力なフレームワーク、
AtomJSと
LibCanvasがあり、アクセサーの使用が完全に
成果を
上げました。 あなたが9番目のバージョン以下のロバを放棄する余裕があるなら-それは価値がある、たくさんの喜びを得る。
このトピックで説明されているソリューションは、わずかに拡張されており
、当初
はAtomJS-Accessorsプラグインとして実装され
ていました 。