JavaScript nu este un limbaj orientat pe obiecte bazat pe clase. Dar are încă modalități de utilizare a programării orientate pe obiecte (OOP).

În acest tutorial, voi explica OOP și vă voi arăta cum să îl utilizați.

Conform Wikipedia, programarea pe clase este

un stil de programare orientată pe obiecte (OOP) în care moștenirea are loc prin definirea claselor de obiecte, în loc de moștenire care se produce numai prin obiecte

Cel mai popular model de POO este bazat pe clase.

Dar, așa cum am menționat, JavaScript nu este un limbaj bazat pe clasificare – este un limbaj bazat pe prototip.

Conform documentației Mozilla:

Un limbaj bazat pe prototip are noțiunea de obiect prototipic, un obiect folosit ca șablon din care să obțină proprietățile inițiale pentru un obiect nou.

Aruncați o privire la acest cod:

let names = {
    fname: "Dillion",
    lname: "Megida"
}
console.log(names.fname);
console.log(names.hasOwnProperty("mname"));
// Expected Output
// Dillion
// false

Variabila obiect names are doar două proprietăți – fname și lname . Fără metode deloc.

Deci, unde este hasOwnProperty vine din?

Ei bine, vine din Object prototip.

Încercați să conectați conținutul variabilei la consolă:

console.log(names);

Când extindeți rezultatele în consolă, veți obține acest lucru:

Programare orientata pe obiecte in JavaScript explicata cu
console.log (nume)

Observați ultima proprietate – __proto__? Încercați să o extindeți:

1611704108 770 Programare orientata pe obiecte in JavaScript explicata cu
Proprietatea __proto__ a numelor

Veți vedea un set de proprietăți sub Object constructor. Toate aceste proprietăți provin din global Object prototip. Dacă te uiți atent, vei observa și ascunsul nostru hasOwnProperty .

Cu alte cuvinte, toate obiectele au acces la Objectprototipul lui. Nu posedă aceste proprietăți, dar li se oferă acces la proprietățile din prototip.

__proto__ proprietate

Aceasta indică obiectul care este folosit ca prototip.

Aceasta este proprietatea de pe fiecare obiect care îi oferă acces la Object prototype proprietate.

Fiecare obiect are această proprietate în mod implicit, care se referă la Object Protoype cu excepția cazului în care este configurat altfel (adică când este al obiectului __proto__ este arătat către un alt prototip).

Modificarea __proto__ proprietate

Această proprietate poate fi modificată declarând în mod explicit că ar trebui să se refere la un alt prototip. Pentru a realiza acest lucru sunt utilizate următoarele metode:

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);

În consolă, iată ce ați avea:

1611704108 366 Programare orientata pe obiecte in JavaScript explicata cu
console.log (bingo)

Observați __proto__ proprietate și speak metodă?

Object.create folosește argumentul care i-a fost transmis pentru a deveni prototipul.

new cuvânt cheie

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__ proprietatea este îndreptată către DogObjectprototipul lui. Dar amintește-ți, DogObjectprototipul este un obiect (pereche cheie și valoare), deci are și un __proto__ proprietate care se referă la global Object prototip.

Această tehnică este denumită ÎNCADENIREA PROTOTIPULUI.

Rețineți că: new abordarea cuvintelor cheie face același lucru ca și Object.create() dar o face mai ușoară, deoarece face anumite lucruri automat pentru dvs.

Așadar…

Fiecare obiect din Javascript are acces la Objectprototipul este implicit. Dacă este configurat pentru a utiliza un alt prototip, să spunem prototype2, atunci prototype2 ar avea, de asemenea, acces la prototipul obiectului în mod implicit și așa mai departe.

Combinație Obiect + Funcție

Probabil că sunteți confuz de faptul că DogObject este o funcție (function DogObject(){}) și are proprietăți accesate cu un notație punct. Aceasta este denumită a combinație de obiecte funcționale.

Când funcțiile sunt declarate, în mod implicit li se oferă o mulțime de proprietăți atașate. Amintiți-vă că funcțiile sunt, de asemenea, obiecte în tipurile de date JavaScript.

Acum, Clasa

JavaScript a introdus fișierul class cuvânt cheie în ECMAScript 2015. Face ca JavaScript să pară un limbaj OOP. Dar este doar zahăr sintatic față de tehnica de prototipare existentă. Își continuă prototiparea în fundal, dar face ca corpul exterior să arate ca OOP. Vom analiza acum cum este posibil acest lucru.

Următorul exemplu este o utilizare generală a class în 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);

Acesta este rezultatul în consolă:

1611704108 267 Programare orientata pe obiecte in JavaScript explicata cu
console.log (bingo)

__proto__ face referiri la Animals prototip (care la rândul său face referire la Object prototip).

Din aceasta, putem vedea că constructorul definește trăsăturile majore în timp ce totul în afara constructorului (sing() și dance()) sunt caracteristicile bonusului (prototipuri).

În fundal, folosind new abordarea cuvântului cheie, cele de mai sus se traduc în:

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");

Subclasificarea

Aceasta este o caracteristică în OOP în care o clasă moștenește caracteristici dintr-o clasă părinte, dar posedă caracteristici suplimentare pe care părintele nu le are.

Ideea aici este, de exemplu, să spui că vrei să creezi un pisici clasă. În loc să creeze clasa de la zero – afirmând Nume, vârstă și specii proprietate din nou, veți moșteni acele proprietăți de la părinte animale clasă.

Acest pisici clasa poate avea apoi proprietăți suplimentare precum culoarea mustăților.

Să vedem cum se fac subclasele class.

Aici avem nevoie de un părinte din care moștenește subclasa. Examinați următorul cod:

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");

Cu cele de mai sus, obținem următoarele rezultate:

console.log(clara.sing());
console.log(clara.whiskers());
// Expected Output
// "Clara can sing"
// "I have indigo whiskers"

Când deconectați conținutul clarului în consolă, avem:

1611704108 920 Programare orientata pe obiecte in JavaScript explicata cu
console.log (clara)

Veți observa asta clara are o __proto__ proprietate care face referire la constructor Cats și primește acces la whiskers() metodă. Acest __proto__ proprietatea are și o __proto__ proprietate care face referire la constructor Animals obținând astfel acces la sing() și dance(). name și age sunt proprietăți care există pe fiecare obiect creat din aceasta.

Folosind Object.create abordare metodică, cele de mai sus se traduc prin:

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 este o metodă care include două argumente – obiectul (primul argument) și prototipul dorit (al doilea argument).

Din cele de mai sus, Animals funcția returnează un obiect cu animalConstructor ca prototip. Cats funcția returnează un obiect cu catConstructor ca prototip. catConstructor pe de altă parte, i se oferă un prototip de animalConstructor.

Prin urmare, animalele obișnuite au acces doar la animalConstructor dar pisicile au acces la catConstructor si animalConstructor.

Încheierea

JavaScript își folosește natura prototip pentru a întâmpina dezvoltatorii OOP în ecosistemul său. De asemenea, oferă modalități ușoare de a crea prototipuri și de a organiza date conexe.

Limbajele OOP adevărate nu realizează prototipuri în fundal – luați notă de acest lucru.

O mare mulțumire Will Sentancecursul Frontend Masters – JavaScript: Părțile dificile ale JavaScript orientate pe obiecte. Am învățat tot ce vedeți în acest articol (plus puțină cercetare suplimentară) din cursul său. Ar trebui să o verifici.

Puteți să mă loviți pe Twitter la iamdillion pentru orice întrebări sau contribuții.

Multumesc pentru citire 🙂

Resurse utile