A JavaScript nem osztályalapú objektum-orientált nyelv. De még mindig vannak módjai az objektum-orientált programozás (OOP) használatára.
Ebben az oktatóanyagban elmagyarázom az OOP-t és megmutatom, hogyan kell használni.
A Wikipedia szerint az osztályalapú programozás az
az objektum-orientált programozás (OOP) stílusa, amelyben az öröklődés az objektumok osztályainak meghatározásán keresztül történik, ahelyett, hogy az öröklés csak az objektumokon keresztül történne
Az OOP legnépszerűbb modellje az osztályalapú.
De mint említettem, a JavaScript nem osztályozott alapú langauge, hanem prototípus-alapú langauge.
A Mozilla dokumentációja szerint:
A prototípus-alapú nyelv egy prototípusos objektum fogalmát képezi, egy olyan objektumot, amelyet sablonként használnak, és amelyből megkapja az új objektum kezdeti tulajdonságait.
Vessen egy pillantást erre a kódra:
let names = { fname: "Dillion", lname: "Megida" } console.log(names.fname); console.log(names.hasOwnProperty("mname")); // Expected Output // Dillion // false
Az objektumváltozónak names
csak két tulajdonsága van - fname
és lname
. Nincsenek módszerek.
Tehát honnan hasOwnProperty
származik?
Nos, ez a Object
prototípusból származik .
Próbálja meg naplózni a változó tartalmát a konzolon:
console.log(names);
Ha kibővíti az eredményeket a konzolon, akkor ezt kapja:

Figyelje meg az utolsó tulajdonságot - __proto__
? Próbáld kibővíteni:

A Object
konstruktor alatt megjelenik egy sor tulajdonság . Mindezek a tulajdonságok a globális Object
prototípusból származnak . Ha alaposan megnézi, észreveszi a rejtetteket is hasOwnProperty
.
Más szavakkal, minden objektum hozzáférhet a Object
prototípushoz. Nem rendelkeznek ezekkel a tulajdonságokkal, de hozzáférést kapnak a prototípus tulajdonságaihoz.
Az __proto__
ingatlan
Ez a prototípusként használt objektumra mutat.
Ez az ingatlan minden objektumon, amely hozzáférést biztosít az Object prototype
ingatlanhoz.
Alapértelmezés szerint minden objektumnak ez a tulajdonsága van, amely a kivételre vonatkozik, Object Protoype
kivéve, ha másként van beállítva (vagyis amikor az objektum __proto__
egy másik prototípusra mutat).
Az __proto__
ingatlan módosítása
Ez a tulajdonság úgy módosítható, hogy kifejezetten kijelenti, hogy egy másik prototípusra kell hivatkoznia. Ennek elérésére a következő módszereket alkalmazzák:
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);
A konzolban ez van:

Figyelje meg a __proto__
tulajdonságot és a speak
módszert?
Object.create
a neki átadott érvet használja prototípussá.
new
kulcsszó
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__
tulajdon irányul DogObject
” s prototípus. De ne feledje, DogObject
hogy a prototípus egy objektum ( kulcs és értékpár ), ezért rendelkezik egy __proto__
tulajdonsággal, amely a globális Object
prototípusra utal .
Ezt a technikát prototípus láncolásnak nevezik .
Vegye figyelembe, hogy: a new
kulcsszó megközelítés ugyanazt csinálja, mint, Object.create()
de csak megkönnyíti, mivel egyes dolgokat automatikusan elvégez az Ön számára.
És aztán...
A Javascript minden objektuma Object
alapértelmezés szerint hozzáfér a prototípushoz. Ha például egy másik prototípus használatára van beállítva prototype2
, akkor prototype2
alapértelmezés szerint hozzáférhet az Object prototípusához is, és így tovább.
Objektum + Funkció kombináció
Valószínűleg megzavarja az a tény, hogy DogObject
ez egy függvény ( function DogObject(){}
), és tulajdonságai pontszerű jelöléssel érhetők el . Ezt függvényobjektum-kombinációnak nevezzük .
A függvények deklarálásakor alapértelmezés szerint sok tulajdonságot kapnak hozzá. Ne feledje, hogy a függvények a JavaScript adattípusainak objektumai is.
Most, osztály
A JavaScript class
az ECMAScript 2015-ben vezette be a kulcsszót. A JavaScript OOP nyelvnek tűnik. De ez csak a szintatikus cukor a meglévő prototípus-készítési technikához képest. A háttérben folytatja a prototípus-készítést, de a külső test OOP-hoz hasonlít. Most megvizsgáljuk, hogy ez hogyan lehetséges.
Az alábbi példa az a általános használata a class
JavaScript-ben:
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);
Ez a konzol eredménye:

A prototípusra __proto__
hivatkozik Animals
(amely viszont a Object
prototípusra hivatkozik ).
Ebből láthatjuk, hogy a konstruktor meghatározza a főbb jellemzőket, míg a konstruktoron ( sing()
és dance()
) kívül minden a bónusz tulajdonság ( prototípus ).
A háttérben, a new
kulcsszó megközelítés alkalmazásával, a fentiek fordítása:
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");
Alosztályozás
Ez az OOP egyik olyan jellemzője, ahol egy osztály örökli a tulajdonságokat a szülő osztálytól, de rendelkezik olyan extra tulajdonságokkal, amelyek a szülők nem.
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
.
Therefore, ordinary animals only have access to the animalConstructor
but cats have access to the catConstructor
and the animalConstructor
.
Wrapping Up
JavaScript leverages its prototype nature to welcome OOP developers to its ecosystem. It also provides easy ways to creating prototypes and organize related data.
True OOP languages do not perform prototyping in the background - just take note of that.
A big thanks to Will Sentance's course on Frontend Masters - JavaScript: The Hard Parts of Object Oriented JavaScript. I learned everything you see in this article (plus a little extra research) from his course. You should check it out.
You can hit me up on Twitter at iamdillion for any questions or contributions.
Thanks for reading : )
Useful Resources
- Object-oriented JavaScript for beginners
- Introduction to Object Oriented Programming in JavaScript