"this" a reliable reference?

12

Situation

I was putting together a widget when I started to analyze a possible error, because the tests 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 n methods should at first be called via np () , ie function, however I remembered the call method and apply , which change the this , to the calling object.

Doubt

  • Should I always do objectName.var instead of this.var ?
asked by anonymous 22.03.2016 / 13:10

1 answer

10

Guilherme, in the following passage:

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

This becomes the current function, if you want to get 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';
}

This is the object that called the method ... in a normal situation it will be n itself, but when using the call (this), the caller is this and it does not have a property options . then go to n.options

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

(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>
    
22.03.2016 / 13:52