javascript – Is "this" a reliable reference?

Question:

Situation

I was assembling a widget when I started to analyze a possible error, because by the tests it actually occurred:

Test

document.getElementById('teste').addEventListener('click', function(){
  n.p.call(this);
  setTimeout(function(){
    document.getElementById('result').innerHTML = 'FAIL';
    n.q.call(this);
  },2000);
});

var n = {
  options : {
    move : true,
  },
  p : function(){
    console.log(this);
    document.getElementById('result').innerHTML = this;
  },
  q : function(){
    if(this.options.move === true){
      console.log()
      document.getElementById('result').innerHTML = 'OK';
    }
  }
}

n.p();
setTimeout(function(){
  n.q();
},2000);
<p id="teste">
  teste
</p>
<div id="result">
</div>

Description

The methods of n at first should be called via np() , that is, function, however I remembered the call and apply method, which change this , for the calling object.

He doubts

  • How to reference this , when this is not what I expected?
  • Should I always do objectName.var instead of this.var ?

Answer:

Guilherme, in the following excerpt:

setTimeout(function(){
    document.getElementById('result').innerHTML = 'FAIL';
    n.q.call(this);
},2000);

The this becomes the current function, if you want to get the this from the previous scope (in this case the div#teste ), store it in a variable.

As for the following excerpt:

if(this.options.move === true){
    console.log()
    document.getElementById('result').innerHTML = 'OK';
}

The this is the object that called the method … in a normal situation will be the own n , but when using the call (this), who is calling the method is this and this is not a property options . then go to n.options

if you need more control over your scope, use a closure or implement the EventListener interface

(function () {
  var teste = document.getElementById('teste');
  var result = document.getElementById('result');

  teste.addEventListener('click', function(){
    var self = this;
    n.p.call(self);
    setTimeout(function(){
      result.innerHTML = 'FAIL';
      n.q.call(self);
    },2000);
  });

  var n = {
    options : {
      move : true,
    },
    p : function(){
      console.log(this);
      result.innerHTML = this;
    },
    q : function(){
      if(n.options.move === true){
        console.log(this)
        result.innerHTML = 'OK';
      }
    }
  }

  n.p();
  setTimeout(function(){
    n.q();
  },2000);
})();
<p id="teste">
  teste
</p>
<div id="result">
</div>

an example implementing the EventListener interface:

var n = {
  teste: document.getElementById('teste'),
  result: document.getElementById('result'),
  options : {
    move : true,
  },
  p : function(){
    console.log(this);
    result.innerHTML = this;
  },
  q : function(){
    if(this.options.move === true){
      console.log(this)
      result.innerHTML = 'OK';
    }
  },
  handleEvent: function (event) {
    if (event.currentTarget == this.teste && event.type == "click") {
      this.exec();
    }
  },
  exec: function () {
    var self = this;
    this.p();
    setTimeout(function(){
      self.q();
    }, 2000);
  },
  init: function () {
    this.teste.addEventListener('click', this);
    this.exec();
  }
};

n.init();
<p id="teste">
  teste
</p>
<div id="result">
</div>
Scroll to Top