user1817517
user1817517

Reputation: 349

confuse with 'this' keyword in jquery

Please help, I couldn't figure this out.

function Tour(el) {
  var tour = this;
  this.el = el;
  this.fetchPhotos = function() { 
    $.ajax('/photos.html', {
      data: {location: tour.el.data('location')},
      context: tour,
      success: function(response) {
        this.el.find('.photos').html(response).fadeIn();
      },
      error: function() {
        this.el.find('.photos').html('<li>There was a problem fetching the latest photos. Please try again.</li>');
      },
      timeout: 3000,
      beforeSend: function() {
        this.el.addClass('is-fetching');
      },
      complete: function() {
        this.el.removeClass('is-fetching');
      }
    });
  }
  this.el.on('click', 'button', this.fetchPhotos);
}
$(document).ready(function() { 
  var paris = new Tour($('#paris'));
});

in the function above, I know the context: tour sets this inside the this.fetchPhotos function to reference Tour. So my question is why can this part of code tour.el.data('location') change to this.el.data('location')?

Thank you in advanced for your help

Upvotes: 0

Views: 85

Answers (2)

doodeec
doodeec

Reputation: 2927

As charlietfl wrote, this is a different context inside ajax callbacks, you have to cache this to any variable before ajax call and use that variable. Like you did in tour variable:

function Tour(el) {
  var tour = this;
  this.el = el;
  this.fetchPhotos = function() { 
    $.ajax('/photos.html', {
      data: {location: tour.el.data('location')},
      context: tour,
      success: function(response) {
        tour.el.find('.photos').html(response).fadeIn();
      },
      error: function() {
        tour.el.find('.photos').html('<li>There was a problem fetching the latest photos. Please try again.</li>');
      },
      timeout: 3000,
      beforeSend: function() {
        tour.el.addClass('is-fetching');
      },
      complete: function() {
        tour.el.removeClass('is-fetching');
      }
    });
  }
  this.el.on('click', 'button', this.fetchPhotos);
}
$(document).ready(function() { 
  var paris = new Tour($('#paris'));
});

Outside of the ajax call (like the click event binder) it is ok to use this, but in those callback functions, it refers to that callback handler

Upvotes: 0

Paul Draper
Paul Draper

Reputation: 83273

The reason that works is because tour.el.data('location') is called from fetchPhotos.

As long as you do

new Tour().fetchPhotos();

and not

var f = new Tour().fetchPhotos;
f();

the replacement will work.

But doing

this.el.on('click', 'button', this.fetchPhotos);

is like the latter. It does not work the same.

Upvotes: 3

Related Questions