191

インスタンス メソッドをイベント ハンドラーのコールバックとして使用すると、スコープがthis" My instance"から"Whatever just called the callback" に変更されます。だから私のコードは次のようになります

function MyObject() {
  this.doSomething = function() {
    ...
  }

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}

それは機能しますが、それが最善の方法ですか?私には奇妙に見えます。

4

8 に答える 8

218

この質問は jQuery に固有のものではなく、一般的な JavaScript に固有のものです。中心的な問題は、組み込み関数で変数を「チャネル化」する方法です。これは例です:

var abc = 1; // we want to use this variable in embedded functions

function xyz(){
  console.log(abc); // it is available here!
  function qwe(){
    console.log(abc); // it is available here too!
  }
  ...
};

この手法は、クロージャーの使用に依存しています。ただし、スコープからスコープに動的に変化する可能性のある疑似変数であるthisため、動作しません。this

// we want to use "this" variable in embedded functions

function xyz(){
  // "this" is different here!
  console.log(this); // not what we wanted!
  function qwe(){
    // "this" is different here too!
    console.log(this); // not what we wanted!
  }
  ...
};

私たちは何ができる?それをいくつかの変数に割り当て、エイリアスを介して使用します。

var abc = this; // we want to use this variable in embedded functions

function xyz(){
  // "this" is different here! --- but we don't care!
  console.log(abc); // now it is the right object!
  function qwe(){
    // "this" is different here too! --- but we don't care!
    console.log(abc); // it is the right object here too!
  }
  ...
};

thisはこの点で一意ではありません:arguments同じように扱われるべき他の疑似変数です — エイリアシングによる.

于 2008-12-03T17:58:14.540 に答える
18

ええ、これは共通の基準のようです。自分を使うコーダーもいれば、私を使うコーダーもいます。イベントではなく、「実際の」オブジェクトへの参照として使用されます。

それは本当に理解するのに少し時間がかかったもので、最初は奇妙に見えます.

私は通常、オブジェクトの一番上でこれを行います (私のデモ コードを許してください。これは何よりも概念的なものであり、優れたコーディング テクニックのレッスンではありません)。

function MyObject(){
  var me = this;

  //Events
  Click = onClick; //Allows user to override onClick event with their own

  //Event Handlers
  onClick = function(args){
    me.MyProperty = args; //Reference me, referencing this refers to onClick
    ...
    //Do other stuff
  }
}
于 2008-12-03T17:11:05.713 に答える
14

ES2015 を実行している場合、またはタイプ スクリプトと ES5 を実行している場合は、コードでアロー関数を使用でき、そのエラーに直面することはなく、これはインスタンスで目的のスコープを参照します。

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});

説明として: ES2015 では、アロー関数thisはその定義スコープからキャプチャします。通常の関数定義はそうしません。

于 2016-09-12T22:39:31.690 に答える
12
var functionX = function() {
  var self = this;
  var functionY = function(y) {
    // If we call "this" in here, we get a reference to functionY,
    // but if we call "self" (defined earlier), we get a reference to function X.
  }
}

編集: それにもかかわらず、オブジェクト内のネストされた関数は、周囲のオブジェクトではなくグローバル ウィンドウ オブジェクトを使用します。

于 2015-04-26T18:07:11.230 に答える
4

これに対する 1 つの解決策は、javascript のbindメソッドを使用して、すべてのコールバックをオブジェクトにバインドすることです。

名前付きメソッドでこれを行うことができます。

function MyNamedMethod() {
  // You can now call methods on "this" here 
}

doCallBack(MyNamedMethod.bind(this)); 

または匿名のコールバックを使用

doCallBack(function () {
  // You can now call methods on "this" here
}.bind(this));

に頼る代わりにこれらを行うことでvar self = this、バインディングが JavaScript でどのようにthis動作し、クロージャー参照に依存しないかを理解していることがわかります。

また、ES6 の太い矢印演算子は、基本的に.bind(this)無名関数の呼び出しと同じです。

doCallback( () => {
  // You can reference "this" here now
});
于 2016-06-01T18:55:50.690 に答える
3

私は jQuery を使用していませんが、Prototype のようなライブラリでは、関数を特定のスコープにバインドできます。それを念頭に置いて、コードは次のようになります。

 $('#foobar').ready('click', this.doSomething.bind(this));

bind メソッドは、指定したスコープで元のメソッドを呼び出す新しい関数を返します。

于 2008-12-03T17:16:16.340 に答える
2

これに追加するだけで、矢印関数のためにES6で値をキャプチャするため、これを行う必要はありませんthis

于 2015-10-29T21:56:31.200 に答える
1

実際には、関数内で何をするかによって異なると思いますdoSomethingMyObjectこのキーワードを使用してプロパティにアクセスする場合は、それを使用する必要があります。ただし、プロパティを使用して特別なことをしていない場合は、次のコード フラグメントも機能すると思いobject(MyObject)ます。

function doSomething(){
  .........
}

$("#foobar").ready('click', function(){

});
于 2008-12-03T17:10:06.790 に答える