0

だから私はこのようなjavascript/Backboneスクリプトを持っています:

var Model = Backbone.Model.extend({});

var View = Backbone.View.extend({

 initialize: function() {
    _.bindAll(this); //bind this
   this.doProcessing();
 },

 doProcessing: function() {

  $('.someElement').each(function() {
      Model myModel = new Model;
      myModel.fetch({                          //issue ajax
         success: function(model, response){   //after successful ajax
            console.log(this)                  // <-- outputs Window!!
       });     

   }); //end each

  } //end processing

});

new View;

私を逃れるのは、どのようthisにしてウィンドウにバインドされるかです。私は自分のクロージャをよく知っていますが、 ?thisを参照するべきではありません。model

これが私が理解していることです-成功のコールバックはどういうわけかウィンドウオブジェクトにバインドされています。したがって、呼び出されたときのコンテキストは、ウィンドウオブジェクトのコンテキストです。しかし、私の意見では、それは少し予想外の動作です。バックボーンがそれを行う理由(または私が何かを誤解しているのですか?)

のパラメータを使用myModelしてのプロパティを設定するのは少し奇妙です。単純なものを許可する必要があるときに呼び出すのはかなり複雑なようですmodelsuccessmodel.set({...})this.set({...})

この場合、私の理解はthis正しいですか?回避策はありますか?それとも、これはXHRが成功コールバックにバインドする方法の多くですか?

バックボーンのソース(Model.fetch)から:

fetch: function(options) {
      options = options ? _.clone(options) : {}; //cloning options - does this variable get bound to global?
      var model = this;
      var success = options.success;            //or is it this?
      options.success = function(resp, status, xhr) {
        if (!model.set(model.parse(resp, xhr), options)) return false;
        if (success) success(model, resp);
      };
      options.error = Backbone.wrapError(options.error, model, options);
      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    },
4

4 に答える 4

1

「成功のコールバックは、どういうわけかウィンドウオブジェクトにバインドされています」

いいえ、JavaScriptの関数は「バインド」されていません。this関数が呼び出されたときにのみ指定されるもの。それがどのように呼ばれるか見てみましょう

success(model, resp)

したがって、関数は、メソッド呼び出し構文(someObj.someMethod(...))や、またはを介して.call()ではなく、直接呼び出されます.apply()。したがって、この場合、thisはグローバルオブジェクト(この場合はウィンドウ)に設定されます。

于 2012-08-05T07:48:57.103 に答える
0

回避策の1つは、このようなことを試すことです。

myModel.fetch({                          
     success: _.bind(function(model, response){   
        console.log(this);                  
   },this);
});     
于 2012-08-04T04:12:30.873 に答える
0

.call()または.apply()は特定のコンテキストを指定しておらず、オブジェクトwindowとしての使用にフォールバックするため、これはデフォルトで発生しますthis

于 2012-08-04T04:58:24.247 に答える
0

ブロックのコンテキスト、または参照しているものは、javascriptthisでは非常に不安定です。

コンテキストの変更はブロック内で行われると思いますが、動作$('.someElement').each(function() { ... });には何の関係もありませんModel.fetch()

次のようなログを追加してみてください。

doProcessing: function() {
  console.log( "out of the block", this );

  $('.someElement').each(function() {
    console.log( "begining of block", this );

    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", this );                 
      }     
    });
  };

  console.log( "end of block", this );
}

ブロックには、ループへの実際のDOM要素が含まれている必要がありますeachthis

このthis意味の変化を解決するために、私が使用していて、周りを見回している回避策は、ブロックthis外の別の変数を参照し(いつが期待されるか)、この新しい参照を使用してブロック:this

doProcessing: function() {
  console.log( "out of the block", this );

  var _self = this;

  $('.someElement').each(function() {
    console.log( "begining of block", _self );

    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", _self );
      }     
    });
  };

  console.log( "end of block", this );
}

アップデート

最近作成したモデルを参照する場合は、次のように作成した外部参照を使用してください。

doProcessing: function() {
  $('.someElement').each(function() {
    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", myModel );                 
      }     
    });
  };
}

または、Backboneが成功コールバックに送信している参照を使用します。

doProcessing: function() {
  $('.someElement').each(function() {
    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", model );                 
      }     
    });
  };
}
于 2012-08-04T09:57:47.667 に答える