4

すべての自動プロパティをタイマーで監視するなどの大きなオーバーヘッドなしに、関数呼び出しで設定せずに、プロパティが変更されたときにJavaScriptに関数をバインドする方法があるかどうか知りたいです。たとえば、私はあなたが次のようなことをすることができることを知っています:

var c = new (function () {
    this.Prop = 'test';
    this.Prop_get = function (value) {
        return('Prop = ' + this.Prop);
    };
    this.Prop_set = function (value) {
        if (value != 'no') {
            this.Prop = value;
        }
    };
})();

document.write(c.Prop_get());
document.write('<BR />');
c.Prop_set('no');
document.write(c.Prop_get());
document.write('<BR />');
c.Prop_set('yes');
document.write(c.Prop_get());
document.write('<BR />');

しかし、私は以下が同じ結果を生み出すことを可能にするいくつかの方法を探しています:

document.write(c.Prop);
document.write('<BR />');
c.Prop = 'no';
document.write(c.Prop);
document.write('<BR />');
c.Prop = 'yes';
document.write(c.Prop);
document.write('<BR />');

変更または同様にオーバーヘッドの高いソリューションについてPropプロパティを監視するタイマーを追加する以外の、疑似クラスへの変更。

4

2 に答える 2

3

この問題の解決策は、サポートする必要があるものに帰着します。

IE6-IE8が必要な場合は、タイマーやDOMのひどい悪用に頼って、非表示のDOMオブジェクトに変更を加え、リッスン可能なイベントなどを発生させる方がおそらく賢明です。

これらのブラウザをある種のミューテーション対応ライブラリに準拠させるための取り組みについて話しているブログがいくつかあります。
結果と警告は異なります。

ES5準拠のブラウザについて話している場合、ほとんどの場合、オブジェクト内で直接「get」および「set」キーワードをサポートしています。
これにより、C#よりもクリーンなコンストラクター/インターフェイスが作成される可能性があります。コンストラクターはと同じくらい単純な場合もありますが、Javaのリスト、、、ではvar a = {};なく、魔法のメソッドを使用することもできます。また、メソッドとは何かを覚えようとするという頭痛の種もあります。インターフェイスに到達したときのプロパティ。getXgetYz

真剣に、これはちょっときれいです:

var person = {
    person_name : "Bob",
    get name () { return this.person_name; },
    set name (value) {
        console.log("But my parents named me " + this.person_name + "!");
    }
};


person.name;
person.name = "Mark";

しかし、ここには問題がありperson.person_nameます。プライベートではありません。
誰でも急襲してそれを変えることができます。

心配する必要はgetありsetません。実際にオブジェクトのプロパティを操作する必要はありません。

var Person = function (name, age) {
    // we don't need to save these; closures mean they'll be remembered as arguments
    // I'm saving them as `private_*` to illustrate
    var private_name = name,
        private_age  = age;

    var public_interface = {
        get name () { return private_name; },
        set name (value) { console.log("Nope!"); },
        get age () { return private_age; },
        set age (value) { console.log("Nope!"); },
        set court_appointed_name (value) {
            console.log("If I must...");
            private_name = value;
        }
    };

    return public_interface;
};

var mark = Person("Mark", 32);
mark.name; // "Mark";
mark.name = "Bubba"; // log: "Nope!";
mark.name; // "Mark";
mark.court_appointed_name = "Jim-Bob"; // log: "If I must..."
mark.name; // "Jim-Bob"

また、auth-tokensなどを使用して、割り当てを強制的にオブジェクトに渡すこともできます。

mark.name = {
    value : "Jimmy Hoffa",
    requested_by : system.user.id,
    auth : system.user.auth.token
};

これはすべて素晴らしいですね。
どうしてやらないの?

ブラウザのサポート。

問題は、これにはまったく新しい構文が必要なことです。すべてのオブジェクトはキーと値のペアとして定義されます。
構文をいじると、プログラム全体をtry / catchでラップしない限り、サポートされていないブラウザーがクラッシュして書き込みます(これはパフォーマンスの自殺です)。

1回のtry-catchテストを実行し、ページの読み込みで、見苦しい回避策とは対照的に、すばらしいインターフェースを遅延読み込みすることができます。これは、それを実行する正しい方法ですが、現在、アプリケーションの2つのバージョンを開発しています。

または、場合によっては3つのバージョン(新しいブラウザー、FF3のような中間ブラウザー、およびGhetto_IEのハック)。

使用される中間ブラウザ{}.__defineGetter__{}.__defineSetter__
Object.prototype.defineProperty(/ .defineProperties)は、古いバージョンのIEが(実際のDOMツリーにアタッチされた)DOMオブジェクトの変更のみをサポートしていることに気付くまで、IEの互換性への期待を植え付けるメソッドです。やったー。

于 2013-02-17T23:29:26.600 に答える
1

ゲッターとセッターに関連するこのリンクに出くわした後、これに対する解決策を見つけました。誰かがそれに興味を持っている場合、結果として私がまとめたオブジェクトにプロパティを適用する一般的な方法は次のとおりです。

Object.prototype.Property = function (name, fn) {
    if (fn.hasOwnProperty('get')) { this.__defineGetter__(name, fn.get); }
    else { this.__defineGetter__(name, function () { throw ('Cannot read property ' + name + '.'); }); }
    if (fn.hasOwnProperty('set')) { this.__defineSetter__(name, fn.set); }
    else { this.__defineSetter__(name, function () { throw ('Cannot write property ' + name + '.'); }); }
};

function C() {
    var _Field = 'test';
    this.Property('Field', {
        get: function () {
            return ('Field = ' + _Field);
        },
        set: function (value) {
            if (value != 'no') {
                _Field = value;
            }
        }
    });
};
C.prototype.constructor = C;

var c = new C();
document.write(c.Field);
document.write('<BR />');
c.Field = 'no';
document.write(c.Field);
document.write('<BR />');
c.Field = 'yes';
document.write(c.Field);
document.write('<BR />');

編集:上記のようなJQuery対応のObject.prototype.Property関数:

Object.defineProperty(Object.prototype, 'Property', {
    enumerable: false,
    value: function (name, fn) {
        if (fn.hasOwnProperty('get')) { this.__defineGetter__(name, fn.get); }
        else { this.__defineGetter__(name, function () { throw ('Cannot read property ' + name + '.'); }); }
        if (fn.hasOwnProperty('set')) { this.__defineSetter__(name, fn.set); }
        else { this.__defineSetter__(name, function () { throw ('Cannot write property ' + name + '.'); }); }
    }
});

そして、動作するJSFiddle

于 2013-02-17T22:29:18.303 に答える