15 dicembre 2021

Metodi di prototype, objects senza __proto__

Nel primo capitolo di questa sezione, abbiamo menzionato il fatto che esistono metodi piu moderni per impostare il prototype.

La proprietà __proto__ viene considerata datata, e in un certo senso anche deprecata (negli standard JavaScript per i browser).

Alcuni dei metodi più moderni sono:

Questi metodi dovrebbero sempre essere preferiti a __proto__.

Ad esempio:

let animal = {
  eats: true
};

// creiamo un nuovo oggetto con animal come prototype
let rabbit = Object.create(animal);

alert(rabbit.eats); // true

alert(Object.getPrototypeOf(rabbit) === animal); // true

Object.setPrototypeOf(rabbit, {}); // cambia il prototype di rabbit a {}

Object.create supporta un secondo argomento opzionale: il property descriptors (descrittori di proprietà). Possiamo fornire proprietà aggiuntive al nuovo oggetto, in questo modo:

let animal = {
  eats: true
};

let rabbit = Object.create(animal, {
  jumps: {
    value: true
  }
});

alert(rabbit.jumps); // true

I descrittori vanno forniti nel formato descritto nel capitolo Attributi e descrittori di proprietà.

Possiamo utilizzare Object.create per clonare un oggetto in maniera più efficace rispetto al copiare le proprietà con un for..in:

let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

Questa chiamata crea una copia esatta di obj, inculdendo tutte le proprietà: enumerable e non-enumerable, e i relativi setters/getters – tutto, impostando anche il giusto [[Prototype]].

Una breve storia

Se contiamo tutti i modi che abbiamo a disposizione per gestire [[Prototype]], questi sono molti! Abbiamo moltissime modalità per fare la stessa cosa!

Perché?

Motivazioni storiche.

  • La proprietà "prototype" di un costruttore è disponibile fin dai primi tempi in JavaScript.
  • Più tardi, nel 2012, è apparso nello standard Object.create. Il quale permette di creare oggetti fornendogli un prototype, ma non consente di impostarlo o di ottenerlo. Quindi i browser implementarono il metodo non-standard __proto__, come proprietà di accesso per impostare o otternere il prototype in qualsiasi momento.