El artículo original lo he escrito en Platzi.

Debido a que muchas personas tienen problemas para entender this en JavaScript, me decidí por escribir una pequeña guía que ayude a entender un poco mejor este concepto.

Primero que nada hay que entender que this no es algo fijo, sino que siempre va a estar en constante cambio y depende de en donde y como se use.

this dentro de una función

Si nosotros ejecutamos la siguiente función:

function imprimeThis() {
   console.log(this);
};

imprimeThis();

Vamos a obtener el objeto global window:

Window {frames: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}

this intenta devolver un objeto; Como la function no es un objeto, se va a un nivel más arriba y encuentra al objeto window, es por ello por lo que en este caso this es igual a window.

this === window
true

En resumen, si this esta en el contexto global o en una función como la del ejemplo, este nos va a devolver window.

Ahora cambiemos un poco nuestro código:

function imprimeThis() {
   "use strict"; // Ahora ponemos use strict
   console.log(this);
};

imprimeThis();

En este caso nos va a devolver: undefined, ya que el use strict no permite que se convierta en el objeto global (window).

this dentro de un método

Si this esta dentro de una función, pero esta función pertenece a un objeto, su valor cambia.

let perro = {
  nombre: "Max",
  saludar: function() {
    return`Hola, me llamo ${this.nombre} Guau Guau`;
  }
};

En este caso, this se refiere al objeto perro.

Si nosotros ejecutamos lo siguiente:

perro.saludar();

Esto nos va a devolver:

"Hola, me llamo Max Guau Guau"

this dentro de un EVENT HANDLER

Un EVENT HANDLER es una función que se ejecuta cuando se dispara algún evento, por ejemplo cuando se hace click en cierto elemento.

HTML
<a href="#" id="boton">Yo soy un botón</a>
Javascript
const boton = document.getElementById("boton");

boton.addEventListener("click", function() {
  console.log(this.textContent);
});

Si nosotros le damos click a dicho botón, se imprimiría en consola: Yo soy un botón. Se extrajo el texto de nuestro HTML porque this en este caso, es nuestro elemento HTML.

This dentro de un constructor:

En este caso, this se refiere al objeto instanciado.

Con ECMAScript 5
function Persona(nombre, edad) {
  this.nombre = nombre;
  this.edad = edad;
}

let amigo = new Persona("Mario", 50);
let hermana = new Persona("Claudia", 27);
let madre = new Persona("María", 60);
Con ECMAScript 6
class Persona{
  constructor(nombre, edad) {
    this.nombre = nombre;
    this.edad = edad;
  }

}

let amigo = new Persona("Mario", 50);
let hermana = new Persona("Claudia", 27);
let madre = new Persona("María", 60);

amigo:

Persona {nombre: "Mario", edad: 50}

hermana:

Persona {nombre: "Claudia", edad: 27}

madre:

Persona {nombre: "María", edad: 60}

En conclusión el this, en la función constructora se refiere al objeto instanciado.

this en un arrow function:

Las arrow functions tienen algo llamado Lexical this, que nos permiten con this llegar a un nivel superior de la función.

Por ejemplo si nosotros tenemos la clase Persona, y queremos aumentar su edad cada segundo, usamos el siguiente código´

class Persona{
  constructor() {
    this.edad = 0;
  }

  aumentarEdad() {
    setInterval(function(){
      this.edad++;
      console.log(this.edad);
    }, 1000)
  }
}

let fili = new Persona(); 

Si ejecutamos:

fili.aumentarEdad();

El resultado va a ser NAN cada segundo. Esto es porque this realmente es un objeto window (como vimos anteriormente), y lo que Javascript hace en this.edad++ realmente es window.edad++, es por ello por lo que regresa NaN (Not a Number).

Con los arrow functions no pasa esto, this en este caso va a tomar el valor que tiene this, fuera del contexto en el cual fue creada esa función. Es decir, en la clase Persona.

class Persona {
  constructor() {
    this.edad = 0;
  }

  aumentarEdad() {
    setInterval(() => {
      this.edad++;
      console.log(this.edad);
    }, 1000)
  }
}

let fili = new Persona();

Si ejecutamos:

fili.aumentarEdad();

Como resultado, edad va a ir aumentando de uno en uno cada segundo, y este se va a ir mostrando en consola.

Espero que esta pequeña guía te haya ayudado a entender un poco mejor como es que this cambia dependiendo de la situación en la que se encuentre. Te invito a probar diferentes situaciones usando los ejemplos que acabas de ver.

Te recomiendo leer el siguiente artículo, si quieres saber aún más sobre this:
https://medium.com/entendiendo-javascript/entendiendo-this-javascript-cba60c8cec8c