Cos’è una catena di prototipi in JavaScript?

Febbraio 15, 2025

In JavaScript, le funzioni possono avere proprietà. Tutte le funzioni hanno una proprietà speciale chiamata prototype.

function doSomething() {} 
console.log(doSomething.prototype); 
// Le funzioni in JavaScript hanno sempre una proprietà prototype di default
// Eccezione: le funzioni freccia non hanno una proprietà prototype di default
const doSomethingFromArrowFunction = () => {}; 
console.log(doSomethingFromArrowFunction.prototype); 

doSomething() ha una proprietà prototype di default. Dopo aver eseguito il codice sopra, la console mostrerà un oggetto simile al seguente:

{ constructor: ƒ doSomething(), [[Prototype]]: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } 

Nota: la console di Chrome usa [[Prototype]] per rappresentare il prototipo dell’oggetto, secondo la terminologia della specifica; Firefox usa .prototype. Per uniformità, useremo [[Prototype]].

Possiamo aggiungere proprietà al prototipo di doSomething():

function doSomething() {} 
doSomething.prototype.foo = "bar"; 
console.log(doSomething.prototype); 

Risultato:

{ foo: "bar", constructor: ƒ doSomething(), [[Prototype]]: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } 

Usiamo l’operatore new per creare un’istanza di doSomething() basata su questo prototipo. Chiamare una funzione con l’operatore new restituisce un oggetto che è un’istanza della funzione. Le proprietà possono quindi essere aggiunte a questo oggetto.

function doSomething() {} 
doSomething.prototype.foo = "bar"; // aggiungi una proprietà al prototipo
const doSomeInstancing = new doSomething(); 
doSomeInstancing.prop = "some value"; // aggiungi una proprietà all'oggetto
console.log(doSomeInstancing); 

Risultato:

{ prop: "some value", [[Prototype]]: { foo: "bar", constructor: ƒ doSomething(), [[Prototype]]: { constructor: ƒ Object(), hasOwnProperty: ƒ hasOwnProperty(), isPrototypeOf: ƒ isPrototypeOf(), propertyIsEnumerable: ƒ propertyIsEnumerable(), toLocaleString: ƒ toLocaleString(), toString: ƒ toString(), valueOf: ƒ valueOf() } } } 

[[Prototype]] di doSomeInstancing è doSomething.prototype. Quando si accede a una proprietà di doSomeInstancing, il runtime prima controlla se doSomeInstancing ha quella proprietà.

In caso contrario, il runtime cercherà la proprietà in doSomeInstancing.[[Prototype]] (cioè doSomething.prototype). Se doSomeInstancing.[[Prototype]] ha la proprietà che si sta cercando, allora quella proprietà verrà utilizzata.

Altrimenti, verrà controllato doSomeInstancing.[[Prototype]].[[Prototype]]. Per impostazione predefinita, [[Prototype]] della proprietà prototype di qualsiasi funzione è Object.prototype. Quindi, verrà cercato doSomeInstancing.[[Prototype]].[[Prototype]] (cioè doSomething.prototype.[[Prototype]] o Object.prototype). Questo processo è chiamato catena di prototipi.

Se la proprietà non viene trovata in doSomeInstancing.[[Prototype]].[[Prototype]], verrà cercato doSomeInstancing.[[Prototype]].[[Prototype]].[[Prototype]]. Tuttavia, doSomeInstancing.[[Prototype]].[[Prototype]].[[Prototype]] non esiste, perché Object.prototype.[[Prototype]] è null. Dopo che l’intera catena di prototipi è stata cercata, il runtime affermerà che la proprietà non esiste e il valore della proprietà è undefined.

function doSomething() {} 
doSomething.prototype.foo = "bar"; 
const doSomeInstancing = new doSomething(); 
doSomeInstancing.prop = "some value"; 
console.log("doSomeInstancing.prop: ", doSomeInstancing.prop); 
console.log("doSomeInstancing.foo: ", doSomeInstancing.foo); 
console.log("doSomething.prop: ", doSomething.prop); 
console.log("doSomething.foo: ", doSomething.foo); 
console.log("doSomething.prototype.prop:", doSomething.prototype.prop); 
console.log("doSomething.prototype.foo: ", doSomething.prototype.foo); 

Risultato:


doSomeInstancing.prop: some value
doSomeInstancing.foo: bar
doSomething.prop: undefined
doSomething.foo: undefined
doSomething.prototype.prop: undefined
doSomething.prototype.foo: bar

Leave A Comment

Categorie

Recent Posts

Create your account