Double Nested “this”

I encountered a problem today that i’m not sure how to deal with efficiently. As you can see in the code below there are three buttons, when one of them is clicked they all move to a designated spot, and then the button that was clicked changes color.

This was what I was hoping to achieve initially, however the background-color changes instantly without giving the buttons a chance to “arrive at their destinations”. I tried to combat this by using a setTimeout(), but the nested function does not recognize the this.

$('.groupOfButtons').on('click', function(){
  $('#oneButton').animate({
      left:"425px",
      top:"-=24px"
  }, 1000)
  $('#anotherButton').animate({
      left:"273px",
      top:"+=5px"
  }, 1000)
  $('#oneMoreButton').animate({
      left:"137px",
      top:"+=34px"
  }, 1000)
  setTimeout(function(){
      $(this).css({'background-color': 'green'})}, 1000) // here!
  })
})

If someone could give me a workaround that would be great! But in the meantime I’m curious about double nested this’s. How would one use it within one or more functions? Is it possible?


solution

Within the setTimeout function callback, this references the global window object.

You need to capture the value of this outside of that scope:

$('.groupOfButtons').on('click', function(){
  var self = this;


  $('#oneButton').animate({
      left:"425px",
      top:"-=24px"
  }, 1000)
  $('#anotherButton').animate({
      left:"273px",
      top:"+=5px"
  }, 1000)
  $('#oneMoreButton').animate({
      left:"137px",
      top:"+=34px"
  }, 1000)
  setTimeout(function(){
      $(self).css({'background-color': 'green'});
  }, 1000);
});

Also, as Félix pointed out in the comments, you can also change the value of this by using the .bind() method on the function:

setTimeout(function(){
  $(this).css({'background-color': 'green'});
}.bind(this), 1000);