Konstruktor, operátor nový

Běžné {...} syntaxe nám umožňuje vytvořit jeden objekt. Často však potřebujeme vytvořit mnoho podobných objektů, například více uživatelů nebo položek nabídky a tak dále.

To lze provést pomocí funkcí konstruktoru a "new" operátor.

Funkce konstruktoru

Funkce konstruktoru jsou technicky běžné funkce. Existují však dvě konvence:

  1. Jsou pojmenovány s velkým počátečním písmenem.
  2. Měly by být spouštěny pouze s "new" operátor.

Například:

function User(name) {
 this.name = name;
 this.isAdmin = false;
}

let user = new User("Jack");

alert(user.name); // Jack
alert(user.isAdmin); // false

Když je funkce spuštěna s new , provede následující kroky:

  1. Je vytvořen nový prázdný objekt a přiřazen k this .
  2. Tělo funkce se provede. Obvykle upravuje this , přidá do něj nové vlastnosti.
  3. Hodnota this je vráceno.

Jinými slovy new User(...) dělá něco jako:

function User(name) {
 // this = {}; (implicitly)

 // add properties to this
 this.name = name;
 this.isAdmin = false;

 // return this; (implicitly)
}

Takže let user = new User("Jack") dává stejný výsledek jako:

let user = {
 name: "Jack",
 isAdmin: false
};

Nyní, pokud chceme vytvořit další uživatele, můžeme zavolat new User("Ann") , new User("Alice") a tak dále. Mnohem kratší než pokaždé používat literály a také snadno čitelné.

To je hlavní účel konstruktorů – implementovat opakovaně použitelný kód pro vytváření objektů.

Poznamenejme ještě jednou – technicky jde o jakoukoli funkci (kromě funkcí šipek, protože nemají this ) lze použít jako konstruktor. Může být spuštěn s new a provede výše uvedený algoritmus. „Velké písmeno napřed“ je běžná dohoda, aby bylo jasné, že funkce má být spuštěna s new .

new function() { … }

Pokud máme mnoho řádků kódu o vytvoření jediného komplexního objektu, můžeme je zabalit do okamžitě volané funkce konstruktoru, jako je tato:

// create a function and immediately call it with new
let user = new function() {
 this.name = "John";
 this.isAdmin = false;

 // ...other code for user creation
 // maybe complex logic and statements
 // local variables etc
};

Tento konstruktor nelze znovu volat, protože není nikde uložen, pouze vytvořen a volán. Cílem tohoto triku je tedy zapouzdřit kód, který vytváří jediný objekt, bez budoucího opětovného použití.

Test režimu konstruktoru:new.target

Pokročilé věci

Syntaxe z této sekce se používá zřídka, přeskočte ji, pokud nechcete vědět všechno.

Uvnitř funkce můžeme zkontrolovat, zda byla volána pomocí new nebo bez něj, pomocí speciálního new.target vlastnost.

Pro běžná volání není definována a rovná se funkci, je-li volána s new :

function User() {
 alert(new.target);
}

// without "new":
User(); // undefined

// with "new":
new User(); // function User { ... }

To lze použít uvnitř funkce, abyste zjistili, zda byla volána s new , „v režimu konstruktoru“, nebo bez něj, „v běžném režimu“.

Můžeme také udělat oba new a běžná volání, aby udělali totéž, jako je toto:

function User(name) {
 if (!new.target) { // if you run me without new
 return new User(name); // ...I will add new for you
 }

 this.name = name;
}

let john = User("John"); // redirects call to new User
alert(john.name); // John

Tento přístup se někdy používá v knihovnách, aby byla syntaxe flexibilnější. Aby lidé mohli volat funkci s nebo bez new a stále to funguje.

Pravděpodobně není dobré používat všude, protože vynechání new je trochu méně zřejmé, co se děje. S new všichni víme, že se vytváří nový objekt.

Návrat od konstruktorů

Konstruktory obvykle nemají return tvrzení. Jejich úkolem je zapsat všechny potřebné věci do this a automaticky se stane výsledkem.

Ale pokud existuje return pak je pravidlo jednoduché:

  • Pokud return je volána s objektem, pak je vrácen objekt namísto this .
  • Pokud return je voláno s primitivem, je ignorováno.

Jinými slovy return s objektem vrátí tento objekt, ve všech ostatních případech this je vráceno.

Například zde return přepíše this vrácením objektu:

function BigUser() {

 this.name = "John";

 return { name: "Godzilla" }; // <-- returns this object
}

alert( new BigUser().name ); // Godzilla, got that object

A zde je příklad s prázdným return (nebo bychom za něj mohli umístit primitiv, na tom nezáleží):

function SmallUser() {

 this.name = "John";

 return; // <-- returns this
}

alert( new SmallUser().name ); // John

Konstruktéři obvykle nemají return tvrzení. Zde zmiňujeme speciální chování s vracejícími se objekty především pro úplnost.

Vynechání závorek

Mimochodem, za new můžeme vynechat závorky , pokud nemá žádné argumenty:

let user = new User; // <-- no parentheses
// same as
let user = new User();

Vynechání závorek zde není považováno za „dobrý styl“, ale syntaxe je povolena specifikací.

Metody v konstruktoru

Použití funkcí konstruktoru k vytváření objektů poskytuje velkou flexibilitu. Funkce konstruktoru může mít parametry, které definují, jak vytvořit objekt a co do něj vložit.

Samozřejmě můžeme přidat do this nejen vlastnosti, ale také metody.

Například new User(name) níže vytvoří objekt s daným name a metodu sayHi :

function User(name) {
 this.name = name;

 this.sayHi = function() {
 alert( "My name is: " + this.name );
 };
}

let john = new User("John");

john.sayHi(); // My name is: John

/*
john = {
 name: "John",
 sayHi: function() { ... }
}
*/

Chcete-li vytvářet složité objekty, existuje pokročilejší syntaxe, třídy, kterým se budeme věnovat později.

Shrnutí

  • Funkce konstruktoru nebo stručně konstruktory jsou běžné funkce, ale existuje společná shoda na jejich pojmenování s velkým počátečním písmenem.
  • Funkce konstruktoru by měly být volány pouze pomocí new . Takové volání znamená vytvoření prázdného this na začátku a vrácení obsazeného na konci.

Můžeme použít funkce konstruktoru k vytvoření více podobných objektů.

JavaScript poskytuje funkce konstruktoru pro mnoho vestavěných jazykových objektů:například Date pro data Set pro sady a další, které plánujeme studovat.

Objekty, my se vrátíme!

V této kapitole pokryjeme pouze základy o objektech a konstruktorech. Jsou nezbytné, abyste se v dalších kapitolách dozvěděli více o datových typech a funkcích.

Poté, co se to naučíme, vrátíme se k objektům a podrobně se jim budeme věnovat v kapitolách Prototypy, dědičnost a Třídy.