3

関数をクリックにバインドするイベントがあります。クリックすると、同じビューで別の関数が呼び出されます。残念ながら、スコープは正しいスコープではありません。this.otherFunction()を実行しようとすると、クリックに割り当てられた関数がthis.otherFunction()と同じスコープにありません。otherFunction()のスコープを渡す方法はありますか?

initialize: function() {
  this.render();

  if (joinedGoalList.get(this.model.id) != null) {
    this.renderLeaveGoal();
  } else {
    this.renderJoinGoal();
  }
},

events: {
  "keypress #goal-update": "createOnEnter",
  "click #join-goal": "joinGoal",
  "click #leave-goal": "leaveGoal",
},

joinGoal: function() {
  matches = joinedGoalList.where({id: this.model.get("id")});
  if (matches.length == 0) {
    joinedGoalList.create({goal_id: this.model.get("id")}, {wait: true, success: function() {
      var self = this;
      self.renderLeaveGoal();
    }, error: function() {
      console.log("error");
    }});
  }
},

renderLeaveGoal: function() {
  console.log("render leave goal");
  var template = _.template($("#leave-goal-template").html());
  console.log(template);
  $("#toggle-goal-join").html(template());
},

これらはすべて同じビューの下にあります。

編集:うーん、今問題は私がこのエラーを受け取ることです:Uncaught TypeError:Object[objectDOMWindow]にはメソッド'renderLeaveGoal'がありません。これは私が間違ったスコープを保存したように見えますか?

4

4 に答える 4

5

標準的なテクニックは次のようなことをすることです

var self = this;

その後、あなたはすることができます

self.otherFunction();

代わりに

this.otherFunction();
于 2012-04-21T02:15:14.420 に答える
2

deltanovemberの答えは正しいですが、彼はそれが正しい理由を説明していませんでした。それが重要だと思います。

Javascriptではスコープが乱雑です。それを追跡する最も簡単な方法は、何かがいつ実行されるかを考えることです。コードのブロックがすぐに実行される場合、それはおそらく「this」と同じスコープで実行されています。関数が後で呼び出される場合は、「this」という独自の概念を使用して、完全に異なるスコープで実行されている可能性があります。

あなたの例では、成功コールバックとして提供している無名関数は後で実行され、そのコールバックが定義されたときに実行されているコードと同じ「this」にスコープされません。これがエラーが発生する理由です。renderLeaveGoalはコールバックが定義されたスコープで定義されましたが、コールバックが実行されるスコープでは定義されていません。

これをさらに混乱させるために、コールバックが定義れたときに定義された変数は、そのコールバックのスコープ内で使用できるようになります。これがdeltanovemberの答えが機能する理由です。成功コールバックが定義されているときに変数の「this」を偽装することにより、スコープが完全に異なっていても、コールバックは後で実行するときに変数にアクセスできます。

それが理にかなっていることを願っています。そうでない場合はコメントしてください。もう一度やり直します:)

于 2012-04-21T08:05:46.840 に答える
2

次のように、アンダースコアのbindAll関数を使用することもできます。

initialize: function() {
    _.bindAll(this);
}

舞台裏では、Underscoreは、オブジェクト内のすべての関数呼び出しを、「this」を元のオブジェクトと同じ「this」に設定するプロキシバージョンに置き換えます。もちろん、メソッドの1つに独自の匿名コールバック関数がある場合は、「self=this」ダンス全体を実行する必要があります。bindAllは、オブジェクトの「外部」メソッドのコンテキストのみを修正します。

ビューの各initialize()メソッドの最初の行として_.bindAllを使用する習慣を身に付けました。

于 2012-04-21T21:56:06.260 に答える
1

関数はビューにアタッチされているため、Viewオブジェクトから呼び出す必要があります。

success: this.renderLeaveGoal

この場合、ビュー関数はビューのコンテキストに自動的にバインドされるため、無名関数は必要ありません。

于 2012-04-21T02:17:38.443 に答える