JavaScript non è un linguaggio orientato agli oggetti basato su classi. Ma ha ancora modi di usare la programmazione orientata agli oggetti (OOP).
In questo tutorial, spiegherò OOP e vi mostrerà come usarlo.
Secondo Wikipedia, di classe, la programmazione
uno stile di programmazione orientata agli Oggetti (OOP) in cui eredità si verifica attraverso la definizione di classi di oggetti, invece di ereditarietà che si verificano attraverso gli oggetti da solo
Il modello più popolare di OOP è basato su classi.
Ma come ho detto, JavaScript non è un langauge basato su classed-è un langauge basato su prototipi.
Secondo la documentazione di Mozilla:
Un linguaggio basato su prototipi ha la nozione di oggetto prototipo, un oggetto utilizzato come modello da cui ottenere le proprietà iniziali per un nuovo oggetto.
date un’occhiata a questo codice:
let names = { fname: "Dillion", lname: "Megida"}console.log(names.fname);console.log(names.hasOwnProperty("mname"));// Expected Output// Dillion// false
La variabile oggetto names
ha solo due proprietà – fname
e lname
. Nessun metodo.
Quindi da dove viene hasOwnProperty
?
Beh, viene dal prototipoObject
.
Prova a registrare il contenuto della variabile nella console:
console.log(names);
Quando espandi i risultati nella console, otterrai questo:
Notare l’ultima proprietà – __proto__
? Prova ad espanderlo:
Vedrai un insieme di proprietà sotto Object
costruttore. Tutte queste proprietà provengono dal prototipo globale Object
. Se guardi da vicino, noterai anche il nostro nascosto hasOwnProperty
.
In altre parole, tutti gli oggetti hanno accesso al prototipo di Object
. Non possiedono queste proprietà, ma hanno accesso alle proprietà nel prototipo.
La proprietà __proto__
Punta all’oggetto che viene utilizzato come prototipo.
Questa è la proprietà su ogni oggetto che gli dà accesso alla proprietà Object prototype
.
Ogni oggetto ha questa proprietà per impostazione predefinita, che fa riferimento aObject Protoype
tranne quando configurato diversamente (cioè quando l’oggetto__proto__
è puntato su un altro prototipo).
Modifica della proprietà __proto__
Questa proprietà può essere modificata specificando esplicitamente che deve fare riferimento a un altro prototipo. I seguenti metodi sono utilizzati per raggiungere questo obiettivo:
Oggetto.create ()
function DogObject(name, age) { let dog = Object.create(constructorObject); dog.name = name; dog.age = age; return dog;}let constructorObject = { speak: function(){ return "I am a dog" }}let bingo = DogObject("Bingo", 54);console.log(bingo);
Nella console, questo è ciò che avresti:
Notare la proprietà__proto__
e il metodospeak
?
Object.create
utilizza l’argomento passato ad esso per diventare il prototipo.
nuova parola chiave
function DogObject(name, age) { this.name = name; this.age = age;}DogObject.prototype.speak = function() { return "I am a dog";}let john = new DogObject("John", 45);
john
‘s __proto__
proprietà è diretto DogObject
‘s prototipo. Ma ricorda, il prototipo di DogObject
è un oggetto (coppia chiave e valore), quindi ha anche una proprietà __proto__
che si riferisce al prototipo globale Object
.
Questa tecnica è indicata come CONCATENAMENTO PROTOTIPO.
Nota che: l’approccio delle parole chiavenew
fa la stessa cosa diObject.create()
ma lo rende solo più semplice in quanto fa alcune cose automaticamente per te.
E così via…
Ogni oggetto in Javascript ha accesso al prototipoObject
per impostazione predefinita. Se configurato per utilizzare un altro prototipo, ad esempio prototype2
, quindi prototype2
avrebbe anche accesso al prototipo dell’Oggetto per impostazione predefinita e così via.
Combinazione oggetto + funzione
Probabilmente sei confuso dal fatto cheDogObject
è una funzione (function DogObject(){}
) e ha proprietà accessibili con una notazione a punti. Questo è indicato come una combinazione di oggetti funzione.
Quando le funzioni vengono dichiarate, per impostazione predefinita vengono fornite molte proprietà ad esso collegate. Ricorda che le funzioni sono anche oggetti nei tipi di dati JavaScript.
Ora, Classe
JavaScript ha introdotto la parola chiaveclass
in ECMAScript 2015. Fa sembrare JavaScript un linguaggio OOP. Ma è solo zucchero sintatico sulla tecnica di prototipazione esistente. Continua la sua prototipazione in background ma rende il corpo esterno simile a OOP. Ora vedremo come è possibile.
Il seguente esempio è un utilizzo generale di un class
in JavaScript:
class Animals { constructor(name, specie) { this.name = name; this.specie = specie; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; }}let bingo = new Animals("Bingo", "Hairy");console.log(bingo);
Questo è il risultato nella console:
Il__proto__
fa riferimento alAnimals
prototipo (che a sua volta fa riferimento alObject
prototipo).
Da questo, possiamo vedere che il costruttore definisce le caratteristiche principali, mentre tutto al di fuori del costruttore (sing()
e dance()
) sono le caratteristiche bonus (prototipi).
In background, utilizzando il new
parola chiave di approccio, di cui sopra si traduce in:
function Animals(name, specie) { this.name = name; this.specie = specie;}Animals.prototype.sing = function(){ return `${this.name} can sing`;}Animals.prototype.dance = function() { return `${this.name} can dance`;}let Bingo = new Animals("Bingo", "Hairy");
creazione di Sottoclassi
Questa è una caratteristica in OOP in cui una classe eredita da una classe genitore, ma possiede caratteristiche extra che il genitore non.
L’idea è, per esempio, dire che si desidera creare un gatti di classe. Invece di creare la classe da zero, indicando nuovamente la proprietà nome, età e specie, erediterai quelle proprietà dalla classe degli animali genitori.
Questa classe di gatti può quindi avere proprietà extra come il colore dei baffi.
Vediamo come vengono fatte le sottoclassi con class
.
Qui, abbiamo bisogno di un genitore da cui eredita la sottoclasse. Esaminare il codice riportato di seguito:
class Animals { constructor(name, age) { this.name = name; this.age = age; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; }} class Cats extends Animals { constructor(name, age, whiskerColor) { super(name, age); this.whiskerColor = whiskerColor; } whiskers() { return `I have ${this.whiskerColor} whiskers`; }}let clara = new Cats("Clara", 33, "indigo");
Con il sopra, otteniamo il seguente output:
console.log(clara.sing());console.log(clara.whiskers());// Expected Output// "Clara can sing"// "I have indigo whiskers"
Quando si accede al contenuto di clara nella console ci sono:
Noterai che clara
ha una proprietà __proto__
che fa riferimento al costruttore Cats
e ottiene l’accesso al whiskers()
metodo. Questa proprietà__proto__
ha anche una proprietà__proto__
che fa riferimento al costruttoreAnimals
ottenendo così l’accesso asing()
edance()
name
eage
sono proprietà che esistono su ogni oggetto creato da questo.
Utilizzando l’approccio del metodoObject.create
, quanto sopra si traduce in:
function Animals(name, age) { let newAnimal = Object.create(animalConstructor); newAnimal.name = name; newAnimal.age = age; return newAnimal;}let animalConstructor = { sing: function() { return `${this.name} can sing`; }, dance: function() { return `${this.name} can dance`; }}function Cats(name, age, whiskerColor) { let newCat = Animals(name, age); Object.setPrototypeOf(newCat, catConstructor); newCat.whiskerColor = whiskerColor; return newCat;}let catConstructor = { whiskers() { return `I have ${this.whiskerColor} whiskers`; }}Object.setPrototypeOf(catConstructor, animalConstructor);const clara = Cats("Clara", 33, "purple");clara.sing();clara.whiskers();// Expected Output// "Clara can sing"// "I have purple whiskers"
Object.setPrototypeOf
è un metodo che accetta due argomenti: l’oggetto (primo argomento) e il prototipo desiderato (secondo argomento).
Da quanto sopra, la funzione Animals
restituisce un oggetto con animalConstructor
come prototipo. La funzioneCats
restituisce un oggetto concatConstructor
come prototipo. catConstructor
d’altra parte, viene fornito un prototipo di animalConstructor
.
Pertanto, gli animali ordinari hanno accesso solo aanimalConstructor
ma i gatti hanno accesso acatConstructor
eanimalConstructor
.
Wrapping Up
JavaScript sfrutta la sua natura prototipo per accogliere gli sviluppatori OOP al suo ecosistema. Fornisce inoltre semplici modi per creare prototipi e organizzare i dati correlati.
I veri linguaggi OOP non eseguono la prototipazione in background – prendi nota di ciò.
Un grande grazie al corso di Will Sentance su Frontend Masters – JavaScript: Le parti difficili di JavaScript orientato agli oggetti. Ho imparato tutto quello che vedi in questo articolo (più un po ‘ di ricerca in più) dal suo corso. Dovresti controllare.
Puoi colpirmi su Twitter a idillion per qualsiasi domanda o contributo.
Grazie per aver letto 🙂