6

次のようなクラスといくつかの静的ヘルパー メソッドがあるとします。

function MyClass (myVar) {
    this.myVar = myVar;

    this.replaceMe = function (value) {
        // this will fail
        this = MyClass.staticHelper( value );

        return this;
    }

    this.revealVar = function () {
        alert( this.myVar );
    }
}

MyClass.staticHelper = function (instance, value) {
    return new MyClass( instance.myVar + value );
}

私がやりたいことは次のようなものです:

var instance = new MyClass( 2 );

instance.revealVar(); // alerts 2
instance.replaceMe( 40 ).revealVar(); // alerts 42

その理由は、私のクラスの構造が少し複雑で、すべての内部変数を毎回手動で割り当てるのではなく、オブジェクト全体を置き換えたくないからです。そうする簡単な方法はありますか?

4

4 に答える 4

2

instance.replaceMe( 40 ).revealVar();アラート 42

わかりました、それでreturn MyClass.staticHelper(this, value);十分です。問題は、次の呼び出しで 2 または 42 をアラートする必要があるかどうかだけです。42 に変更しinstance.revealVar()たい場合は、さらに複雑になります。instance

this = MyClass.staticHelper( value ); // this will fail

thisは共通変数ではなく、キーワードであり、関数の入力方法に応じて設定される現在の実行コンテキストの ThisBinding の値に評価されるため、関数を呼び出すときにのみ設定できます。 .

すべての内部変数を毎回手動で割り当てるのではなく、オブジェクト全体を置き換えます。

残念ながら、instanceオブジェクトのプロパティ (およびクロージャー隠し変数) を変更しないと、変更せずinstancerevealVar()2 のままにする必要があります。

そうする簡単な方法はありますか?

はい、プログラムで実行できます。最も簡単な方法は、現在のインスタンスコンストラクターを (再度)呼び出すことです。これは、キーワードで呼び出された場合と同様です。new

MyClass.call( instance, instance.myVar + value );

ただし、まったく新しいインスタンスを作成する静的関数のようにこれを使用することはできません。replaceMeそれを static メソッドに入れてwithから呼び出すかthis、または単に に直接入れますreplaceMe

最初に完全に新しいインスタンスを返す静的メソッドが必要な場合は、古いインスタンスに新しいプロパティをコピーすることで、それを使用することもできます。

….replaceMe = function(val) {
    var newInst = MyClass.staticHelper(this, val); // new MyClass(this.myVar+val);
    for (var prop in newInst)
        if (newInst.hasOwnProperty(prop))
            this[prop] = newInst[prop];
    return this;
};

これは、古い属性を上書きすることを意味します。また、古いクロージャーは、もはや何も参照されていないため、ガベージコレクションすることができます。

ところで、メソッドをコンストラクターに割り当てるのではなく、プロトタイプに配置することをお勧めします。

于 2013-03-24T14:24:57.620 に答える
0

新しいインスタンスを返すだけではどうですか:

function MyClass(myVar) {
    // ...

    this.replaceMe = function (value) {
        return MyClass.staticHelper(this, value);
    }

    // ...
}

MyClass.staticHelper = function (instance, value) {
    return new MyClass( instance.myVar += value );
}
于 2013-03-24T12:43:36.960 に答える
0

これが Javascript で機能しない理由は 2 つあります。

まず、変数のように見えますが、this実際には関数呼び出し*であるため、代入できません。this=fooと同じbar()=bazです。したがって、次のようなコードを作成することはできません。

a = 5
a.change(10)
alert(a == 10) // nope

第 2 に、可能であったとしても、this=zJavascript は値渡しであるため、その方法はいずれにせよ失敗します。そのため、引数の値を変更する関数を使用することはできません。

a = 5
change(a)
alert(a == 10) // nope

*「is」は「あらゆる点で完全に同一」を意味します

于 2013-03-24T12:50:14.137 に答える
0

私はしばらく前に非常に似たようなことをしたいと思っていました。残念ながら、値を割り当てる方法はありませんthisthisポインターは読み取り専用の変数です。ただし、次善の策は、getter および setter オブジェクトを使用して、インスタンス自体を保持する変数を変更することです。

これは、インスタンスへの単一の参照のみを更新することに注意してください。詳細については、こちらをご覧ください: JavaScript でポインターをシミュレートするより良い方法はありますか?

これがどのように機能するかです:

function MyClass(pointer, myVar) {
    this.myVar = myVar;

    this.replaceMe = function (value) {
        pointer.value = MyClass.staticHelper(this, pointer, value);
        return pointer.value;
    };

    this.revealVar = function () {
        alert(this.myVar);
    };
}

MyClass.staticHelper = function (instance, pointer, value) {
    return new MyClass(pointer, instance.myVar + value);
};

を作成しpointerて使用する方法は次のとおりです。

var instance = new MyClass({
    get value() { return instance; },
    set value(newValue) { instance = newValue; }
}, 2);

instance.revealVar();               // alerts 2
instance.replaceMe(40).revealVar(); // alerts 42

これは最もエレガントなソリューションではありませんが、仕事は完了します。このコードの動作を確認できます: http://jsfiddle.net/fpxXL/1/

于 2013-03-24T14:37:34.983 に答える