Kodokon kodokon.com

this, prototipos y clases

Comprende cómo se resuelve this de forma dinámica, cómo funciona la cadena de prototipos y qué añaden realmente las clases al modelo de objetos.

10 min · 3 preguntas

Abrir esta lección en Kodokon

El valor de this se decide en el punto de llamada, no en el momento de la declaración. Cuatro reglas, en orden decreciente de prioridad: llamar con new, enlace explícito (call, apply, bind), llamar como método (obj.fn()) y una llamada simple (fn()), que produce undefined en modo estricto. El bug más común del mundo real se deriva directamente: extraer un método de su objeto rompe el enlace implícito.

JAVASCRIPT
const user = {
  name: "Ada",
  greet() {
    return "Hello, " + this.name;
  },
};
console.log(user.greet()); // "Hello, Ada"
const detached = user.greet;
// detached(); // TypeError: this is undefined
const bound = user.greet.bind(user);
console.log(bound()); // "Hello, Ada"
El enlace implícito desaparece en cuanto se extrae el método.

Las funciones flecha no tienen su propio this: lo capturan léxicamente del ámbito que las envuelve, igual que una closure. Eso las hace ideales para los callbacks, pero contraproducentes como métodos en objetos literales, donde this apuntará al ámbito exterior. Bajo el capó, cada objeto delega a través de su cadena de prototipos: una propiedad ausente se busca eslabón por eslabón hasta alcanzar null.

JAVASCRIPT
function Animal(name) {
  this.name = name;
}
Animal.prototype.describe = function () {
  return this.name + " is an animal";
};
const dog = new Animal("Rex");
console.log(dog.describe()); // "Rex is an animal"
console.log(Object.getPrototypeOf(dog) ===
  Animal.prototype); // true
console.log(dog.hasOwnProperty("describe")); // false
describe vive en el prototipo, compartido por cada instancia.

La sintaxis class no cambia este modelo: lo hace legible. Los métodos declarados en el cuerpo de la clase aterrizan en Constructor.prototype y por tanto se comparten. Los campos de instancia (incluidas las funciones flecha asignadas como campos) se recrean por instancia: enlace de this garantizado, pero coste de memoria multiplicado. Por último, los campos #private proporcionan privacidad impuesta por el motor, a diferencia de la convención del _guion_bajo.

JAVASCRIPT
class BankAccount {
  #balance = 0;
  deposit(amount) {
    if (amount <= 0) throw new Error("Invalid amount");
    this.#balance += amount;
    return this;
  }
  get balance() {
    return this.#balance;
  }
}
const account = new BankAccount();
account.deposit(50).deposit(25);
console.log(account.balance); // 75
Campo privado impuesto por el motor y una API encadenable.

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. En modo estricto, ¿qué es this durante una llamada simple fn() sin objeto y sin enlace explícito?
    • globalThis
    • undefined
    • El objeto en el que se declaró fn
    • null
  2. ¿Dónde se almacenan los métodos declarados en el cuerpo de una clase (excluyendo los campos)?
    • En cada instancia, copiados en el momento de la construcción
    • En Constructor.prototype, compartidos por todas las instancias
    • En un ámbito interno inaccesible
  3. ¿Qué tiene de especial una función flecha con respecto a this?
    • Enlaza this al objeto que llama, como un método
    • No tiene su propio this y captura el del ámbito que la envuelve
    • Siempre enlaza this a globalThis
    • Prohíbe cualquier acceso a this