3.1 Concetto di prototipi
I prototipi sono uno dei concetti chiave in JavaScript, permettendo agli oggetti di ereditare proprietà e metodi da altri oggetti. A differenza di molti altri linguaggi di programmazione, dove l'ereditarietà è realizzata tramite classi, in JavaScript si basa sui prototipi. Ora vediamo cosa sono i prototipi, come funzionano e come possono essere utilizzati.
Un prototipo in JavaScript è un oggetto dal quale altri oggetti possono ereditare proprietà e metodi. Ogni oggetto in JavaScript ha un riferimento nascosto a un altro oggetto - la proprietà nascosta [[Prototype]], che punta al suo prototipo.
Questo prototipo può avere suoi propri prototipi, formando una catena di prototipi (prototype chain). Le proprietà e i metodi di un oggetto possono essere ereditati attraverso questa catena. Questo permette agli oggetti di condividere funzionalità e di creare gerarchie di oggetti.
Proprietà proto
In JavaScript, ogni oggetto ha una proprietà __proto__, che punta al suo prototipo. Questa proprietà è utilizzata per cercare proprietà e metodi, se non vengono trovati nell'oggetto stesso.
In questo esempio, l'oggetto child eredita il metodo greet() dall'oggetto parent:
const parent = {
greet() {
console.log('Hello from parent');
}
};
const child = {
__proto__: parent
};
child.greet(); // Stamperà: Hello from parent
3.2 Creazione e utilizzo dei prototipi
1. Object.create()
Il metodo Object.create() permette di creare un nuovo oggetto con un prototipo specificato.
Esempio:
const parent = {
greet() {
console.log('Hello from parent');
}
};
const child = Object.create(parent);
child.greet(); // Stamperà: Hello from parent
2. Aggiungere proprietà e metodi al prototipo
Proprietà e metodi possono essere aggiunti al prototipo affinché siano disponibili a tutti gli oggetti che lo ereditano.
In questo esempio, il metodo speak() viene aggiunto al prototipo animal ed è disponibile per l'oggetto dog:
const animal = {
speak() {
console.log(`${this.name} makes a noise.`);
}
};
const dog = Object.create(animal);
dog.name = 'Buddy';
dog.speak(); // Stamperà: Buddy makes a noise.
3. Modifica del prototipo dell'oggetto
Il prototipo di un oggetto può essere modificato tramite il metodo Object.setPrototypeOf().
In questo esempio, il prototipo dell'oggetto duck viene modificato da animal a bird:
const animal = {
speak() {
console.log('Animal speaks');
}
};
const bird = {
fly() {
console.log('Bird flies');
}
};
const duck = {
__proto__: animal,
quack() {
console.log('Duck quacks');
}
};
Object.setPrototypeOf(duck, bird);
duck.fly(); // Stamperà: Bird flies
duck.quack(); // Stamperà: Duck quacks
3.3 Lavorare con i prototipi
1. Controllare il prototipo di un oggetto
Il metodo Object.getPrototypeOf() permette di ottenere il prototipo di un oggetto.
Esempio:
const parent = {
greet() {
console.log('Hello from parent');
}
};
const child = Object.create(parent);
console.log(Object.getPrototypeOf(child) === parent); // Stamperà: true
2. Verificare l'appartenenza di un oggetto a un prototipo
L'operatore instanceof è utilizzato per controllare se un oggetto è un'istanza di un determinato costruttore o prototipo.
Esempio:
function Person(name) {
this.name = name;
}
const john = new Person('John');
console.log(john instanceof Person); // Stamperà: true
3. Iterare sulle proprietà dell'oggetto e del suo prototipo
Per iterare sulle proprietà di un oggetto e del suo prototipo si può utilizzare il ciclo for...in, che elenca tutte le proprietà enumerabili.
Esempio:
const parent = {
greet() {
console.log('Hello from parent');
}
};
const child = Object.create(parent);
child.name = 'Child';
for (let key in child) {
console.log(key);
}
// Stamperà:
// name
// greet
Per iterare solo sulle proprietà proprie dell'oggetto si utilizza il metodo Object.keys() o il ciclo for...of con il metodo Object.entries().
Esempio:
const parent = {
greet() {
console.log('Hello from parent');
}
};
const child = Object.create(parent);
child.name = 'Child';
console.log(Object.keys(child)); // Stamperà: ['name']
for (const [key, value] of Object.entries(child)) {
console.log(key, value);
}
// Stamperà:
// name Child
GO TO FULL VERSION