6

最近頭に浮かんだ問題を解決しようとしています。php (__get、__set) のような、動的な getter と setter を javascript で使用することを希望し、その方法を知っているとしましょう。しかし、javascript にはすべてをキャッチするプロパティがないため、可能なキーのリストを提供し、反復してそれらのみにゲッターとセッターを追加するしかありません。

しかし、問題はそれほど解決されていません。tryしたがって、私の頭に浮かんだ次のアプローチは、とで厄介なハックを使用することでしたcatch。そのため、オブジェクトで名前が定義されていないときはいつでも、をcatchゲッターとして使用し(少なくとも)、コードを再開します。行う。しかし、ここから、次のような用途で 2 番目の問題が発生しました。

console.log(g.someundefinedproperty); 

結果は、例外がスローされることなく、 console.logshowingへの呼び出しになります。undefined元のゲッターとセッターを使用するとどうなるでしょうか。window.undefined結局のところ、失敗して単語や何かのスペルを間違えるたびに呼び出す必要があります。

だから私は試しました

Object.defineProperty(window, 'undefined', {
    get : function ()
    {
         // functional code, including getting the caller and figuring out
         // where we are, and what we have to do... easy :D

         console.log('works');
    },
    set : function ()
    {
         // some couple more fine hacks here
         console.log('this too');
    }
});

残念ながら、undefinedwindow のプロパティは ですconfigurable : false。試行された他のハックは、および内部プロパティwindowを除くオブジェクトのクローン作成でした。そして、新しいオブジェクトで新しいオブジェクトを定義します(皮肉なことに注意してください) 。undefinedwindowundefinedwindow = mybetterwindow

これにより問題が発生しなかったので、私の希望は高かったのですが、システムはwindow設計上上書きできないため、やはり失敗しました。window.prototype私はそれが独自のゲッターを持っていると推測しましたWindow.prototype

この実験の最後のステップとして、undefinedこのプロトタイプのヒット ランを再定義しました。役に立たず、何も変更されませんでした... を作成しようとしましたnew Window()Window、コンストラクターではありません。失敗しました!

アイデアが尽きたので、ここで助けを求めるこの嘆願を書いていることに気づきました。動的なゲッターとセッターの問題 ( ) を解決する方法があれば、the existencial problem of life, universe and everything else私がオブジェクトを使用する方法とはまったく変更されません (ボーナスとして、 にはありませneed to breakhole)fabric of time and spaceまたは構文、私はあなたに話すか、永遠に黙っていることを懇願します:)。

4

2 に答える 2

5

残念ながら、window の未定義のプロパティはconfigurable: false

これは、EcmaScript 5.1以降でのみ当てはまります。以前は、上書き可能でした。

元のゲッターとセッターを使用するとどうなるでしょうかwindow.undefined。結局のところ、単語や何かを台無しにしてスペルを間違えるたびに呼び出す必要があります。

いいえ、うまくいきませんでした。未定義の値とグローバル変数「未定義」には違いがあります。変数は、未定義の値に遭遇するたびに評価されるわけではなくtypeof (void 0)( など)、明示的に使用した場合 ( など) にのみ評価されますg.someprop === undefined

動的なゲッターとセッターの問題を解決する方法はありますか?

解決策は 1 つだけですProxies。残念ながら、これは単なるハーモニー ドラフトであり、現在Firefox の Javascript 1.8.5 でのみサポートされています。

プロパティの __noSuchMethod__ 機能に相当するもの、または JS でそれを実装する方法はありますか?も参照してください。、Javascript オブジェクトに新しいプロパティが追加されたことを検出しますか? またはJavaScript オブジェクトにプロパティが追加されたことを検出する方法は? ポーリング ソリューションを実装します (を介して変更をチェックしますsetInterval)。

クリーンなソリューションを得るには、現在、プロパティ名 ( ) を渡す明示的な getter 関数を使用する必要がありますg.get("someundefinedproperty")

于 2012-12-12T22:32:06.177 に答える
2

達成しようとしていること(未定義のプロパティのグローバルゲッター)は、クロスブラウザーJavaScriptの範囲外です。

最も近い機能は__defineGetter__、すべてのオブジェクトに特定のプロパティを追加するために使用します。

var o = Object.prototype;
o.__defineGetter__("testo", function() { return "yo in testo"; });
alert({}.testo);
alert((new Date()).testo);

http://jsfiddle.net/NLCvs/2/

これは、未定義の可能性のあるプロパティの名前を事前に予測できる場合に役立つことがあります。それでも、未定義 の可能性のあるプロパティのすべてのオブジェクトにアクセサーを追加するのは、非常にハッキーで悪い形式です。

より良いオプションは、未定義のプロパティにアクセスする可能性がある場合にコードをリファクタリングすることです。

function getter(o, n) {
 return typeof o[n] == 'undefined' ? 'some default value' : o[n];
}
var obj = { hello: 'world' };
alert(getter(obj, 'hello'));
alert(getter(obj, 'an_undefined_property'));

さらに良いオプションは、ミックスインを使用して、アクセスする必要のあるデフォルトのプロパティを設定することです。jQuery.extend

var defaults = {
 required: 'this property is required'
};
var my_object = {
 something_else: 'this is something else'
};
var o = jQuery.extend({}, defaults, my_object);

// o.required === 'this property is required'
// o.something_else === 'this is something else'
于 2012-12-12T22:33:04.947 に答える