Objektorienteret programmering i JavaScript - forklaret med eksempler
JavaScript er ikke et klassebaseret objektorienteret sprog. Men det har stadig måder at bruge objektorienteret programmering (OOP) på.
I denne vejledning forklarer jeg OOP og viser dig, hvordan du bruger det.
Ifølge Wikipedia er klassebaseret programmering
en stil med objektorienteret programmering (OOP), hvor arv sker via definerende klasser af objekter i stedet for arv, der sker via objekterne alene
Den mest populære OOP-model er klassebaseret.
Men som jeg nævnte, er JavaScript ikke en klassebaseret langauge - det er en prototype-baseret langauge.
Ifølge Mozillas dokumentation:
Et prototype-baseret sprog har forestillingen om et prototypisk objekt, et objekt, der bruges som en skabelon, hvorfra de oprindelige egenskaber for et nyt objekt kan hentes.
Se på denne kode:
let names = { fname: "Dillion", lname: "Megida" } console.log(names.fname); console.log(names.hasOwnProperty("mname")); // Expected Output // Dillion // false
Objektvariablen names
har kun to egenskaber - fname
og lname
. Ingen metoder overhovedet.
Så hvor hasOwnProperty
kommer der fra?
Nå, det kommer fra Object
prototypen.
Prøv at logge indholdet af variablen på konsollen:
console.log(names);
Når du udvider resultaterne i konsollen, får du dette:

Læg mærke til den sidste ejendom - __proto__
? Prøv at udvide det:

Du får vist et sæt egenskaber under Object
konstruktøren. Alle disse egenskaber kommer fra den globale Object
prototype. Hvis du ser nøje, vil du også bemærke vores skjulte hasOwnProperty
.
Med andre ord har alle objekter adgang til Object
prototypen. De har ikke disse egenskaber, men får adgang til egenskaberne i prototypen.
den __proto__
ejendom
Dette peger på objektet, der bruges som en prototype.
Dette er ejendommen på alle objekter, der giver den adgang til Object prototype
ejendommen.
Hvert objekt har som standard denne egenskab, som refererer til det Object Protoype
medmindre andet er konfigureret (det vil sige når objektet __proto__
peges på en anden prototype).
Ændring af __proto__
ejendommen
Denne egenskab kan ændres ved eksplicit at angive, at den skal henvise til en anden prototype. Følgende metoder bruges til at opnå dette:
Object.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);
I konsollen er dette, hvad du vil have:

Læg mærke til __proto__
ejendommen og speak
metoden?
Object.create
bruger argumentet, der sendes til det, til at blive prototypen.
new
nøgleord
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__
ejendom er rettet mod DogObject
' s prototype. Men husk, at DogObject
prototypen er et objekt ( nøgle- og værdipar ), derfor har den også en __proto__
egenskab, der refererer til den globale Object
protoype.
Denne teknik kaldes PROTOTYPE CHAINING .
Bemærk, at: det new
søgeord tilgang gør det samme som Object.create()
, men kun gør det lettere som det gør nogle ting automatisk for dig.
Også...
Hvert objekt i Javascript har som standard adgang til Object
prototypen. Hvis konfigureret til at bruge en anden prototype, siger prototype2
, så prototype2
ville den også have adgang til Objektets prototype som standard og så videre.
Objekt + funktionskombination
Du er sandsynligvis forvirret af det faktum, at det DogObject
er en funktion ( function DogObject(){}
), og den har egenskaber, der fås med en priknotation . Dette kaldes en funktionsobjektkombination .
Når funktioner erklæres, får de som standard mange egenskaber knyttet til det. Husk, at funktioner også er objekter i JavaScript-datatyper.
Nu, klasse
JavaScript introducerede class
nøgleordet i ECMAScript 2015. Det får JavaScript til at virke som et OOP-sprog. Men det er bare syntetisk sukker over den eksisterende prototypeteknik. Det fortsætter sin prototyping i baggrunden, men får den ydre krop til at ligne OOP. Vi ser nu på, hvordan det er muligt.
Følgende eksempel er en generel brug af a class
i 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);
Dette er resultatet i konsollen:

The __proto__
references the Animals
prototype (which in turn references the Object
prototype).
From this, we can see that the constructor defines the major features while everything outside the constructor (sing()
and dance()
) are the bonus features (prototypes).
In the background, using the new
keyword approach, the above translates to:
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");
Subclassing
This is a feature in OOP where a class inherits features from a parent class but possesses extra features which the parent doesn't.
The idea here is, for example, say you want to create a cats class. Instead of creating the class from scratch - stating the name, age and species property afresh, you'd inherit those properties from the parent animals class.
This cats class can then have extra properties like color of whiskers.
Let's see how subclasses are done with class
.
Here, we need a parent which the subclass inherits from. Examine the following code:
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");
With the above, we get the following outputs:
console.log(clara.sing()); console.log(clara.whiskers()); // Expected Output // "Clara can sing" // "I have indigo whiskers"
When you log the contents of clara out in the console, we have:

You'll notice that clara
has a __proto__
property which references the constructor Cats
and gets access to the whiskers()
method. This __proto__
property also has a __proto__
property which references the constructor Animals
thereby getting access to sing()
and dance()
. name
and age
are properties that exist on every object created from this.
Using the Object.create
method approach, the above translates to:
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
is a method which takes in two arguments - the object (first argument) and the desired prototype (second argument).
From the above, the Animals
function returns an object with the animalConstructor
as prototype. The Cats
function returns an object with catConstructor
as it's prototype. catConstructor
on the other hand, is given a prototype of animalConstructor
.
Derfor har almindelige dyr kun adgang til, animalConstructor
men katte har adgang til catConstructor
og animalConstructor
.
Afslutter
JavaScript udnytter sin prototype-natur for at byde OOP-udviklere velkommen til sit økosystem. Det giver også nemme måder at oprette prototyper og organisere relaterede data på.
Ægte OOP-sprog udfører ikke prototyper i baggrunden - bare vær opmærksom på det.
En stor tak til Will Sentance's kursus om Frontend Masters - JavaScript: De hårde dele af objektorienteret JavaScript. Jeg lærte alt, hvad du ser i denne artikel (plus lidt ekstra research) fra hans kursus. Du burde tjekke det ud.
Du kan slå mig op på Twitter på iamdillion for spørgsmål eller bidrag.
Tak for læsningen :)
Nyttige ressourcer
- Objektorienteret JavaScript til begyndere
- Introduktion til objektorienteret programmering i JavaScript