Where does this point in this first example?

2

There is one thing that I do not understand and it is in this case: the operation of this .

This will always point to the object containing the function and the this will be called from the function, my second this points to the object that I created, but WHY THE FIRST THIS points to the button that is an html element?

onclick is an event, boton.onclick = function() Do I have to see it as if onclick were a property that I give to the button object? Should I interpret it like that? Because come on, button is an html element, I'm here with how to interpret this, or is it that this points to events not only to objects since the event is onclick ?

var boton = document.getElementsByTagName('button')[0];
  boton.onclick = function(){
    console.log(this);

    let XMLrequest = new XMLHttpRequest();
    XMLrequest.onreadystatechange = function() {
      console.log(this);
    }
  }
<html>
<head>
  <title>JSON</title>
  <meta charset="utf-8">


</head>
<body>
  <button>click</button>

</body>
</html>
    
asked by fran 20.12.2017 в 12:00
source

4 answers

6

If you want a very simplified version:

this points to the context. In the event handlers, this is the element that has received the event (the button, the div, the link ...). If you call a function as if it were a method, this is the object. But that the function is declared as a method does not ensure that it is called as such.

If you want a longer and "didactic" version, with examples:

The behavior of this is a little special in Javascript: It indicates the context in which you are executing the code. If you are in the global context (you are not inside any function), this is window . If you call a function simply by using the name of the function, the context is maintained:

console.log(this===window);
function test() {
  console.log(this===window);
  if (this!==window) {
    console.log(this);
  }
}

test();

But in strict mode, the context when calling a function using its name is undefined :

'use strict';

console.log(this===window);
    
function test() {
  console.log(this===window);
  if (this!==window) {
    console.log(this);
  }
}

test();

But if that function is an attribute of an object, then this becomes that object:

function test() {
  console.log('Es window?:' + (this===window));
  if (this!==window) {
    console.log('Es obj?:' + (this===obj));
  }
}

console.log('Modo no estricto');

var obj={ 
  prueba: 'hola'
}

test();

console.log('Como método');

obj.metodo=test;

obj.metodo();

Then, when we define a callback function, we can have problems if we do not know which is the context where the function is executed:

class Contador {

  constructor() {
    this.count=0;
  }
  
  incrementar() {
    this.count++;
  }
}

let c= new Contador()
c.incrementar();
console.log(c.count)

let funcionInc=c.incrementar;

//falla porque el contexto no es un objeto Contador
funcionInc();

Imagine that we have an event that we want to deal with our counter object:

class Contador {

  constructor() {
    this.count=0;
  }
  
  incrementar() {
    if (this.count !== undefined) {
      this.count++;
    } else {
      console.log('No hay count para incrementar!');
    }
  }
}

let c= new Contador();

$('button').on('click',c.incrementar);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>

Solutions to this problem there are several:

One is to surround the execution in another function:

class Contador {

  constructor() {
    this.count=0;
  }
  
  incrementar() {
    if (this.count !== undefined) {
      this.count++;
      console.log(this.count);
    } else {
      console.log('No hay count para incrementar!');
    }
  }
}

let c= new Contador();

$('button').on('click',function () {c.incrementar();});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>

And another solution is to use bind() :

class Contador {

  constructor() {
    this.count=0;
  }
  
  incrementar() {
    if (this.count !== undefined) {
      this.count++;
      console.log(this.count);
    } else {
      console.log('No hay count para incrementar!');
    }
  }
}

let c= new Contador();
//con bind fijamos el contexto
let funcion=c.incrementar.bind(c);

$('button').on('click',funcion);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>

The arrow functions are a bit special, because they assign the context at the moment they are defined, not when they are executed:

class Contador {

  constructor() {
    this.count=0;
    this.incrementar= () => { 
      this.count++;
      console.log(this.count);  
    }
  }
}

let c= new Contador();

//no hace falta bind, el contexto se fijó al declarar la función
$('button').on('click',c.incrementar);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>
    
answered by 20.12.2017 в 16:45
3

MDN define onclick as:

  

A property that returns the click event handler of the current item.

The value that this receives depends on the way in which the function is executed / called, let's see some examples

Example 1

function saludar(){
    console.log(this)
}
<button onclick="saludar()">Saludar</button>

As you can see in this example the this in this case refers to window

Example 2

function saludar(elemento){
    console.log(elemento)
}
<button onclick="saludar(this)">Saludar</button>

In this way, if I wanted this to refer to the element that executes the event, I would have to send it as a parameter in the function that is triggered by the event.

Example 3

var boton = document.querySelector('button');

boton.onclick = function(){
    console.log(this)
}

boton.addEventListener('mouseenter', saludar);

function saludar(){
    console.log(this)
}
<button>Saludar</button>

In either of these two cases this refers directly to the element that triggers the event.

    
answered by 20.12.2017 в 16:34
1

onclick is not an event, it is a method that will be called in case the event occurs. And indeed that method belongs to the object boton .

    
answered by 20.12.2017 в 12:07
1

Good hope I'll help you

this

  

The function of keyword this behaves a little differently in Javascript compared to other languages. It also has some differences between strict mode and non-strict mode.

     

In general, the value of this is determined by how the function is called. It can not be established by a runtime assignment, and this can be different each time the function is called. ES5 introduced the bind () method to set the value of the this function regardless of how it is called.

In this case this will refer to:

<button type="button" name="button">Boton</button>

What would be the object that runs the event I hope you help greetings.

  var boton = document.getElementsByTagName('button')[0];
  boton.onclick = function(){
    console.log("El this es = ",this);

    let XMLrequest = new XMLHttpRequest();
    XMLrequest.onreadystatechange = function() {
      console.log(this);
    }
  }
<button type="button" name="button">Boton</button>

Examples

Global context In the context of global execution (outside of any function), this refers to the global object, whether in strict mode or not.

console.log(this.document === document); // true

// En los navegadores web, el objeto window también es un objeto global:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37

Context of the function

Within a function, the value of this depends on how the function is called.

function f1(){
  return this;
}

 f1() === window; // objeto global

In this case, the value of this is not established by the call. Since the code is not in strict mode, the value of this must always be an object, so by default it is the global object.

function f2(){
  "use strict"; // consultar modo estricto
  return this;
}

 f2() === undefined;
  

Source: MDN

    
answered by 20.12.2017 в 14:20