JavaScript ist keine klassenbasierte objektorientierte Sprache. Aber es gibt immer noch Möglichkeiten, objektorientierte Programmierung (OOP) zu verwenden.
In diesem Tutorial erkläre ich OOP und zeige Ihnen, wie Sie es verwenden.
Laut Wikipedia ist klassenbasierte Programmierung
ein Stil der objektorientierten Programmierung (OOP), bei dem die Vererbung über die Definition von Klassen von Objekten erfolgt, anstatt über die Objekte allein
Das beliebteste Modell von OOP ist klassenbasiert.
Aber wie bereits erwähnt, ist JavaScript keine klassenbasierte Sprache – es ist eine prototypbasierte Sprache.
Laut Mozillas Dokumentation:
Eine prototypenbasierte Sprache hat den Begriff eines prototypischen Objekts, eines Objekts, das als Vorlage verwendet wird, um die anfänglichen Eigenschaften für ein neues Objekt abzurufen.
Sehen Sie sich diesen Code an:
let names = { fname: "Dillion", lname: "Megida"}console.log(names.fname);console.log(names.hasOwnProperty("mname"));// Expected Output// Dillion// false
Die Objektvariable names
hat nur zwei Eigenschaften – fname
und lname
. Überhaupt keine Methoden.
Woher kommt also hasOwnProperty
?
Nun, es kommt vom Object
Prototyp.
Versuchen Sie, den Inhalt der Variablen in der Konsole zu protokollieren:
console.log(names);
Wenn Sie die Ergebnisse in der Konsole erweitern, erhalten Sie Folgendes:
Beachten Sie die letzte Eigenschaft – __proto__
? Versuchen Sie, es zu erweitern:
Unter dem Object
Konstruktor. Alle diese Eigenschaften stammen aus dem globalen Object
Prototyp. Wenn Sie genau hinschauen, werden Sie auch unser verstecktes hasOwnProperty
bemerken .Mit anderen Worten, alle Objekte haben Zugriff auf den Prototyp von Object
. Sie besitzen diese Eigenschaften nicht, erhalten aber Zugriff auf die Eigenschaften im Prototyp.
Die Eigenschaft __proto__
zeigt auf das Objekt, das als Prototyp verwendet wird.
Dies ist die Eigenschaft für jedes Objekt, die ihm Zugriff auf die Object prototype
Eigenschaft gibt.
Jedes Objekt hat standardmäßig diese Eigenschaft, die sich auf Object Protoype
bezieht, außer wenn dies anders konfiguriert ist (dh wenn die __proto__
des Objekts auf einen anderen Prototyp verweist).
Ändern der Eigenschaft __proto__
Diese Eigenschaft kann geändert werden, indem explizit angegeben wird, dass sie sich auf einen anderen Prototyp beziehen soll. Die folgenden Methoden werden verwendet, um dies zu erreichen:
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);
In der Konsole haben Sie Folgendes:
Beachten Sie die __proto__
Eigenschaft und die speak
Methode?
Object.create
verwendet das übergebene Argument, um der Prototyp zu werden.
neues Schlüsselwort
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__
Eigenschaft ist auf DogObject
’s Prototyp gerichtet. Aber denken Sie daran, der Prototyp von DogObject
ist ein Objekt (Schlüssel-Wert-Paar), daher hat er auch eine __proto__
Eigenschaft, die sich auf den globalen Object
protoype .
Diese Technik wird als PROTOTYPVERKETTUNG bezeichnet.
Beachten Sie Folgendes: Der new
Keyword-Ansatz macht dasselbe wie Object.create()
macht es aber nur einfacher, da er einige Dinge automatisch für Sie erledigt.
Und so…
Jedes Objekt in Javascript hat standardmäßig Zugriff auf den Prototyp von Object
. Wenn Sie für die Verwendung eines anderen Prototyps konfiguriert sind, z. B. prototype2
, hat prototype2
standardmäßig auch Zugriff auf den Prototyp des Objekts usw.
Objekt + Funktionskombination
Sie sind wahrscheinlich verwirrt durch die Tatsache, dass DogObject
eine Funktion ist (function DogObject(){}
) und es hat Eigenschaften, auf die mit einer Punktnotation zugegriffen wird. Dies wird als Funktionsobjektkombination bezeichnet.
Wenn Funktionen deklariert werden, erhalten sie standardmäßig viele Eigenschaften. Denken Sie daran, dass Funktionen auch Objekte in JavaScript-Datentypen sind.
Nun hat Class
JavaScript das Schlüsselwort class
in ECMAScript 2015 eingeführt. Es lässt JavaScript wie eine OOP-Sprache erscheinen. Aber es ist nur syntaktischer Zucker gegenüber der bestehenden Prototyping-Technik. Es setzt sein Prototyping im Hintergrund fort, lässt aber den äußeren Körper wie OOP aussehen. Wir werden nun sehen, wie das möglich ist.
Das folgende Beispiel ist eine allgemeine Verwendung eines 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);
Dies ist das Ergebnis in der Konsole:
Der __proto__
verweist auf den Animals
Prototyp (der wiederum auf den Object
Prototyp verweist).
Daraus können wir sehen, dass der Konstruktor die Hauptfunktionen definiert, während alles außerhalb des Konstruktors (sing()
und dance()
) die Bonusfunktionen (Prototypen) sind.
Im Hintergrund, unter Verwendung des new
Schlüsselwortansatzes, wird das Obige übersetzt 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");
Subclassing
Dies ist ein Feature in OOP, bei dem eine Klasse Features von einer übergeordneten Klasse erbt, aber zusätzliche Features besitzt, die die übergeordnete Klasse nicht hat.
Die Idee hier ist zum Beispiel, dass Sie um eine cats-Klasse zu erstellen. Anstatt die Klasse von Grund auf neu zu erstellen und die Eigenschaft name, age und species neu anzugeben, erben Sie diese Eigenschaften von der übergeordneten animals-Klasse.
Diese cats-Klasse kann dann zusätzliche Eigenschaften wie die Farbe der Schnurrhaare haben.
Mal sehen, wie Unterklassen mit class
gemacht werden.
Hier brauchen wir ein Elternteil, von dem die Unterklasse erbt. Untersuchen Sie den folgenden 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");
Mit dem obigen erhalten wir die folgenden Ausgaben:
console.log(clara.sing());console.log(clara.whiskers());// Expected Output// "Clara can sing"// "I have indigo whiskers"
Wenn Sie den Inhalt von clara in der Konsole abmelden, haben wir:
Sie werden feststellen, dass clara
eine __proto__
Eigenschaft hat, die auf den Konstruktor Cats
verweist und Zugriff auf die whiskers()
Methode. Diese __proto__
Eigenschaft hat auch eine __proto__
Eigenschaft, die auf den Konstruktor Animals
und dadurch Zugriff auf sing()
und dance()
name
und age
sind Eigenschaften, die für jedes daraus erstellte Objekt vorhanden sind.
Unter Verwendung des Object.create
Methodenansatzes wird das Obige übersetzt 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
ist eine Methode, die zwei Argumente akzeptiert – das Objekt (erstes Argument) und den gewünschten Prototyp (zweites Argument).
Aus dem Obigen gibt die Animals
Funktion ein Objekt mit der animalConstructor
als Prototyp zurück. Die Cats
Funktion gibt ein Objekt mit catConstructor
als Prototyp zurück. catConstructor
andererseits wird ein Prototyp von animalConstructor
.
Daher haben gewöhnliche Tiere nur Zugriff auf die animalConstructor
aber Katzen haben Zugriff auf die catConstructor
und die animalConstructor
.
Einpacken
JavaScript nutzt seine Prototyp-Natur, um OOP-Entwickler in seinem Ökosystem willkommen zu heißen. Es bietet auch einfache Möglichkeiten, Prototypen zu erstellen und verwandte Daten zu organisieren.
Echte OOP-Sprachen führen kein Prototyping im Hintergrund durch – beachten Sie dies einfach.
Ein großes Dankeschön an Will Sentance’s Kurs über Frontend Masters – JavaScript: Die harten Teile von objektorientiertem JavaScript. Ich habe alles, was Sie in diesem Artikel sehen (plus ein wenig zusätzliche Forschung) aus seinem Kurs gelernt. Du solltest es dir ansehen.
Sie können mich auf Twitter bei iamdillion für Fragen oder Beiträge treffen.
Danke fürs Lesen : )