Poďme demystifikovať „nové“ kľúčové slovo JavaScriptu

Cez víkend som dokončil JavaScript Will Sentance: The Hard Parts. Možno to nebude znieť ako najslávnejší spôsob, ako stráviť víkend, ale absolvovanie kurzu mi prišlo skutočne zábavné a relaxačné. Dotklo sa to funkčného programovania, funkcií vyššieho rádu, uzávierok a asynchrónneho JavaScriptu.

Pre mňa bolo vrcholom kurzu to, ako rozšíril prístupy JavaScriptu k objektovo orientovanému programovaniu (OOP) a demystifikoval kúzlo nového operátora. Teraz dobre rozumiem tomu, čo sa deje pod kapotou, keď sa použije nový pohon.

Objektovo orientované programovanie v JavaScripte

Objektovo orientované programovanie (OOP) je paradigma programovania založená na koncepcii „objektov“. Údaje a funkcie (atribúty a metódy) sú zhromaždené v rámci objektu.

Objekt v jazyku JavaScript je kolekcia párov kľúč - hodnota. Tieto páry kľúč - hodnota sú vlastnosťami objektu. Vlastnosťou môže byť pole, funkcia, samotný objekt alebo akýkoľvek primitívny údajový typ, ako sú reťazce alebo celé čísla.

Aké techniky máme v našom paneli nástrojov jazyka JavaScript na vytváranie objektov?

Predpokladajme, že používateľov vytvárame v hre, ktorú sme práve navrhli. Ako by sme ukladali údaje o používateľoch, ako sú ich mená, body a implementovali metódy, ako je prírastok v bodoch? Tu sú dve možnosti základného vytvárania objektov.

Možnosť 1 - doslovný zápis objektu

let user1 = { name: "Taylor", points: 5, increment: function() { user1.points++; } };

Doslovný objekt JavaScript je zoznam párov mien-hodnota zabalených do zložených zátvoriek. Vo vyššie uvedenom príklade je vytvorený objekt 'user1' a súvisiace dáta sú v ňom uložené.

Možnosť 2 - Object.create ()

Object.create(proto, [ propertiesObject ])

Object.create metódy akceptujú dva argumenty:

  1. proto: objekt, ktorý by mal byť prototypom novovytvoreného objektu. Musí to byť objekt alebo nula.
  2. propertiesObject: vlastnosti nového objektu. Tento argument je voliteľný.

V zásade vložíte do Object.createobjektu, z ktorého chcete dediť, a vráti nový objekt, ktorý dedí z objektu, ktorý ste do neho odovzdali.

let user2 = Object.create(null); user2.name = "Cam"; user2.points = 8; user2.increment = function() { user2.points++; }

Vyššie uvedené základné možnosti vytvárania objektov sú opakované. Vyžaduje, aby bol každý z nich manuálne vytvorený.

Ako to prekonáme?

Riešenia

Riešenie 1 - Generovanie objektov pomocou funkcie

Jednoduchým riešením je napísať funkciu na vytvorenie nových používateľov.

function createUser(name, points) { let newUser = {}; newUser.name = name; newUser.points = points; newUser.increment = function() { newUser.points++; }; return newUser; }

Na vytvorenie používateľa by ste teraz zadali informácie do parametrov funkcie.

let user1 = createUser("Bob", 5); user1.increment();

Funkcia prírastku v príklade vyššie je však iba kópiou pôvodnej funkcie prírastku. Toto nie je dobrý spôsob, ako napísať kód, pretože všetky potenciálne zmeny vo funkcii bude treba vykonať manuálne pre každý objekt.

Riešenie 2 - Použite prototypový charakter JavaScriptu

Na rozdiel od objektovo orientovaných jazykov, ako sú Python a Java, JavaScript nemá triedy. Pri dedení využíva koncept prototypov a reťazenia prototypov.

Pri vytvorení novej poľa, máte automaticky prístup do interné postupy, ako je Array.join, Array.sorta Array.filter. Je to spôsobené tým, že objekty poľa dedia vlastnosti z Array.prototype.

Každá funkcia jazyka JavaScript má vlastnosť prototypu, ktorá je predvolene prázdna. Do tejto vlastnosti prototypu môžete pridať funkcie, ktoré sú v tejto podobe známe ako metóda. Keď sa vykoná zdedená funkcia, hodnota tohto ukazuje na zdedený objekt.

function createUser(name, points) { let newUser = Object.create(userFunction); newUser.name = name; newUser.points = points; return newUser; } let userFunction = { increment: function() {this.points++}; login: function() {console.log("Please login.")}; } let user1 = createUser("Bob", 5); user1.increment();

Keď bol user1objekt vytvorený, vytvoril sa prototyp reťazového puta s userFunction.

Keď user1.increment() je v zásobníku hovorov, tlmočník vyhľadá používateľa1 v globálnej pamäti. Ďalej bude hľadať funkciu prírastku, ale nenájde ju. Tlmočník sa pozrie na ďalší objekt v prototypovom reťazci a nájde tam funkciu prírastku.

Riešenie 3 - nové a toto kľúčové slovo

Thenový operátor sa používa na vytvorenie inštancie objektu, ktorý má funkciu konštruktora.

Keď zavoláme funkciu konštruktora novým, automatizujeme nasledujúce akcie:

  • Vytvorí sa nový objekt
  • Viaže sa thisna objekt
  • Prototypový objekt funkcie konštruktora sa stane vlastnosťou __proto__ nového objektu
  • Vráti objekt z funkcie

To je fantastické, pretože výsledkom automatizácie je menej opakujúci sa kód!

function User(name, points) { this.name = name; this.points = points; } User.prototype.increment = function(){ this.points++; } User.prototype.login = function() { console.log(“Please login.”) } let user1 = new User(“Dylan”, 6); user1.increment();

Použitím prototypového vzoru sa každá metóda a vlastnosť pridá priamo na prototyp objektu.

Tlmočník pôjde hore prototypovým reťazcom a nájde funkciu prírastku vo vlastníctve prototypu používateľa, ktorý je tiež objektom s informáciami v ňom. Pamätajte - Všetky funkcie v JavaScripte sú tiež objektmi . Teraz, keď tlmočník našiel to, čo potrebuje, môže vytvoriť nový kontext lokálneho spustenia, ktorý sa má spustiť user1.increment().

Side note: Difference between __proto__ and prototype

If you are already getting confused about __proto__ and prototype, don’t worry! You are far from the only one to be confused about this.

Prototype is a property of the constructor function that determines what will become the __proto__ property on the constructed object.

So, __proto__ is the reference created, and that reference is known as the prototype chain bond.

Solution 4 — ES6 ‘syntactic sugar’

Other languages allow us to write our shared methods within the object “constructor” itself. ECMAScript6 introduced the class keyword, which allows us to write classes that resemble normal classes of other classical languages. In reality, it is syntactic sugar over JavaScript’s prototypal behavior.

class User { constructor(name, points) { this.name = name; this.points = points; } increment () { this.points++; } login () { console.log("Please login.") } } let user1 = new User("John", 12); user1.increment();

In solution 3, the associated methods were precisely implemented using User.prototype.functionName. In this solution, the same results are achieved but the syntax looks cleaner.

Conclusion

We have now learned more about the different options we have in JavaScript to create objects. While class declarations and thenew operator are relatively easy to use, it is important to understand what is automated.

To recap, the following actions are automated when the constructor function is called with new:

  • A new object is created
  • It binds this to the object
  • The constructor function’s prototype object becomes the __proto__ property of the new object
  • It returns the object from the function

Ďakujem za prečítanie môjho článku a tlieskajte, ak sa vám páčil! Prečítajte si moje ďalšie články, ako napríklad Ako som zostavil svoju aplikáciu Pomodoro Clock a aké som si pri tom vzal ponaučenie.