1. ホーム
  2. javascript

[解決済み] JavaScriptのプロトタイプ関数でthisへの参照を保持する [重複]。

2023-04-05 09:46:55

質問

私はプロトタイプのJavaScriptを使い始めたばかりですが、どのようにすれば this への参照を維持する方法を見つけるのに苦労しています。私が言いたいことを説明しましょう (ここでは jQuery を使用しています)。

MyClass = function() {
  this.element = $('#element');
  this.myValue = 'something';

  // some more code
}

MyClass.prototype.myfunc = function() {
  // at this point, "this" refers to the instance of MyClass

  this.element.click(function() {
    // at this point, "this" refers to the DOM element
    // but what if I want to access the original "this.myValue"?
  });
}

new MyClass();

の冒頭でこのようにすることで、メインオブジェクトへの参照を保持できることは知っています。 myfunc :

var myThis = this;

を使用し、さらに myThis.myValue を使ってメインオブジェクトのプロパティにアクセスします。しかし、プロトタイプ関数の束を MyClass ? への参照を保存しなければならないのでしょうか? this への参照を保存しなければならないのでしょうか?もっと簡単な方法があるように思えます。そして、このような状況についてはどうでしょう。

MyClass = function() {
  this.elements $('.elements');
  this.myValue = 'something';

  this.elements.each(this.doSomething);
}

MyClass.prototype.doSomething = function() {
  // operate on the element
}

new MyClass();

この場合、メインオブジェクトへの参照を作るのに var myThis = this; の元の値でさえも this のコンテキスト内で doSomethingjQuery オブジェクトであり MyClass オブジェクトではありません。

グローバル変数を使用して、参照を保持するように提案されましたが、元の this への参照を保持するためにグローバル変数を使用するよう提案されましたが、それは私には本当に悪い考えのように思えます。私はグローバルな名前空間を汚染したくないし、そのせいで2つの異なる MyClass オブジェクトを互いに干渉することなくインスタンス化することを妨げるように思えます。

何か提案はありますか?私が求めていることを行うためのきれいな方法はありますか?それとも、私のデザインパターン全体に欠陥があるのでしょうか?

どのように解決するのですか?

コンテキストを保持するために bind メソッドは本当に便利です。これは最近リリースされた ECMAScript 第 5 版 仕様の一部であり、この関数の実装はシンプルです (長さはわずか 8 行です)。

// The .bind method from Prototype.js 
if (!Function.prototype.bind) { // check if native implementation available
  Function.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    return function(){ 
      return fn.apply(object, 
        args.concat(Array.prototype.slice.call(arguments))); 
    }; 
  };
}

そして、あなたの例では、このように使うことができます。

MyClass.prototype.myfunc = function() {

  this.element.click((function() {
    // ...
  }).bind(this));
};

もう一つの例

var obj = {
  test: 'obj test',
  fx: function() {
    alert(this.test + '\n' + Array.prototype.slice.call(arguments).join());
  }
};

var test = "Global test";
var fx1 = obj.fx;
var fx2 = obj.fx.bind(obj, 1, 2, 3);

fx1(1,2);
fx2(4, 5);

この二番目の例では bind .

これは基本的に新しい関数を生成し、関数のコンテキストを保持したまま、我々の関数を呼び出す役割を担います ( this の最初の引数として定義される関数コンテキスト( bind .

残りの引数は、単に関数に渡されます。

この例では、関数 fx1 オブジェクトのコンテキスト ( obj.method() ) を使用する場合、単純な関数呼び出しと同じように、このタイプの呼び出しでは this キーワードはグローバルオブジェクトを参照し、それは "グローバルテスト" を警告します。

では fx2 は新しい関数で bind メソッドが生成した新しい関数です。この関数はコンテキストを保持し、引数を正しく渡して呼び出され、quot; obj test 1, 2, 3, 4, 5" を警告します。 バインドされた をバインドしています。