JavaScript Konstruktors – skaidrojums un pielietojums / Constructor

 

Konstruktora metode ir īpaša klases metode, lai izveidotu un inicializētu šīs klases objekta gadījumu.

Piezīme. Šī lapa iepazīstina ar konstruktora sintaksi. Visos objektos esošo konstruktora rekvizītu skatiet sadaļā Object.prototype.constructor.

Tas izskatās šādi:

class Izmēģinājums {
    constructor() {
      this.name = 'Izmēģinājums';
    }
  }
 
  const tests1 = new Izmēģinājums();
 
  console.log(tests1.name);
  // paredzamais iznākums: "Izmēģinājums"

 Sintakse:

constructor() { /* ...kods... */ }
constructor(arguments0) { /* ...kods... */ }
constructor(arguments0, arguments1) { /* ...kods... */ }
constructor(arguments0, arguments1, /* … ,*/ argumentsN) { /* ...kods... */ }

Apraksts

Konstruktors ļauj nodrošināt jebkādu pielāgotu inicializēšanu, kas jāveic, pirms instantizētam objektam var izsaukt citas metodes.

class Persona {
    constructor(vārds) {
      this.vārds = vārds;
    }
 
    introduce() {
      console.log(`Sveiki, mans vārds ir ${this.vārds}`);
    }
  }
 
  const endijs = new Persona("Endijs");
 
  endijs.introduce(); // Sveiki, mans vārds ir Endijs
Ja nenorādīsiet savu konstruktoru, jums tiks nodrošināts noklusējuma konstruktors. Ja jūsu klase ir bāzes klase, noklusējuma konstruktors ir tukšs:
constructor() {}
Ja jūsu klase ir atvasināta klase, noklusējuma konstruktors izsauc vecāku konstruktoru, nododot visus norādītos argumentus:
constructor(...args) {
super(...args);
}
Piezīme. Atšķirība starp precīzo konstruktoru, piemēram, iepriekš minēto, un noklusējuma konstruktoru ir tāda, ka pēdējais faktiski neizsauc masīva iteratoru, izmantojot argumentu izplatīšanu.
Tas ļauj šādam kodam darboties:
class ValidācijasKļūda extends Error {
    izvadaPielāgotuPaziņojumu() {
      return `Validācijas kļūda :-( (Precizējums: ${this.message})`;
    }
  }
 
  try {
    throw new ValidācijasKļūda("Nav pareizs telefona numurs");
  } catch (kļūda) {
    if (kļūda instanceof ValidācijasKļūda) {
      console.log(kļūda.name); // This is Error instead of ValidationError!
      console.log(kļūda.izvadaPielāgotuPaziņojumu());
    } else {
      console.log("Nezināma kļūda", kļūda);
      throw kļūda;
    }
  }
Sagaidāmais rezultāts pēc koda palaišanas:
Error
Validācijas kļūda :-( (Precizējums: Nav pareizs telefona numurs)

Klasei ValidācijasKļūda nav nepieciešams precīzs konstruktors, jo tai nav jāveic nekāda pielāgota inicializācija. Pēc tam noklusējuma konstruktors rūpējas par vecākkļūdas inicializēšanu no norādītā argumenta.

Tomēr, ja jūs sniedzat savu konstruktoru un jūsu klase ir atvasināta no kādas vecākklases, jums ir skaidri jāizsauc vecākklases konstruktors, izmantojot super(). Piemēram:

class ValidācijasKļūda extends Error {
    constructor(ziņa) {
      super(ziņa); // call parent class constructor
      this.nosaukums = "ValidācijasKļūda";
      this.kods = "42";
    }
 
    izvadītPielāgotuZiņu() {
      return `Radusies kļūda :-( (Precizējums: ${this.ziņa}, code: ${this.kods})`;
    }
  }
 
  try {
    throw new ValidācijasKļūda("Nav pareizs telefona numurs");
  } catch (kļūda) {
    if (kļūda instanceof ValidācijasKļūda) {
      console.log(kļūda.nosaukums); // Tagad tā ir validācijas kļūda!
      console.log(kļūda.izvadītPielāgotuZiņu());
    } else {
      console.log("Nezināma kļūda", kļūda);
      throw kļūda;
    }
  }
Un sagaidāmais rezultāts izvadē ir šāds:
ValidācijasKļūda
Radusies kļūda :-( (Precizējums: undefined, code: 42)

Izmantojot jauniegūtās zināšanas varat turpināt šādi:

 

  • (Ja tā ir atvasināta klase) Tiek novērtēts konstruktora pamatteksts pirms super() izsaukuma. Šai daļai tai nevajadzētu piekļūt, jo tā vēl nav inicializēta.
  • (Ja tā ir atvasināta klase) Super() izsaukums tiek novērtēts, kas inicializē vecāku klasi, izmantojot to pašu procesu.
    Pašreizējās klases lauki ir inicializēti.
  • Tiek novērtēts konstruktora pamatteksts pēc super() izsaukuma (vai viss korpuss, ja tas ir bāzes klase).
  • Konstruktora pamattekstā varat piekļūt izveidotajam objektam, izmantojot šo, un piekļūt klasei, kas tiek izsaukta ar new, izmantojot new.target. Ņemiet vērā, ka metodes (ieskaitot getterus un iestatītājus) un prototipu ķēde jau ir inicializētas pirms konstruktora izpildes, tāpēc jūs pat varat piekļūt apakšklases metodēm no virsklases konstruktora. Tomēr, ja šīs metodes to izmanto, tas vēl nebūs pilnībā inicializēts. Tas nozīmē, ka atvasinātās klases publisko lauku lasīšana radīs undefined, savukārt privāto lauku lasīšana radīs TypeError.

Konstruktora metodei var būt atgriešanas vērtība. Lai gan bāzes klase var atgriezt jebko no sava konstruktora, atvasinātajai klasei ir jāatgriež objekts vai nedefinēts, pretējā gadījumā tiks parādīta TypeError.

class VecākuKLase {
    constructor() {
      return 1;
    }
  }
 
  console.log(new VecākuKLase()); // VecākuKlase {}
  // Vērtības atgriešana tiek atcelta, jo tas nav objekts
  // Satur funkciju konstruktorus
 
  class BērnuKLase extends VecākuKLase {
    constructor() {
      return 1;
    }
  }
 
  console.log(new BērnuKLase()); // TypeError: Noteiktie konstruktori var atgriezt objektu vai undefined

Ja vecākklases konstruktors atgriež objektu, šis objekts tiks izmantots kā šī vērtība, kurā tiks definēti atvasinātās klases klases lauki. Šo triku sauc par “atgriešanās ignorēšanu”, kas ļauj atvasinātās klases laukus (tostarp privātos) definēt nesaistītos objektos.

Klasē var būt tikai viena īpaša metode ar konstruktora nosaukumu. Ja klasē ir vairāk nekā viens konstruktora metodes gadījums, tiks parādīta kļūda SyntaxError. Sintakses kļūda ir arī ieguvējs vai iestatītājs, ko sauc par konstruktoru.

Konstruktors ievēro parasto metodes sintaksi, tāpēc var izmantot parametru noklusējuma vērtības, atpūtas parametrus utt.

 class Cilvēks {
    constructor(vārds = "Nezināms") {
      this.vārds = vārds;
    }
    introduce() {
      console.log(`Sveiki, mans vārds ir ${this.name}`);
    }
  }
 
  const cilvēks = new Cilvēks();
  cilvēks.introduce(); // Sveiki, mans vārds ir Nezināms
Konstruktoram ir jābūt burtiskam nosaukumam. Aprēķinātie rekvizīti nevar kļūt par konstruktoriem.

class Testiņš {
    // Šis ir izgūtais. Kods to nepaņems kā konstruktors.
    ["constructor"]() {
      console.log("izsaukts");
      this.a = 1;
    }
  }
 
  const Testiņš = new Testiņš(); // No log
  console.log(Testiņš); // Testiņš {}
  Testiņš.constructor(); // Logs "called"
  console.log(Testiņš); // Testiņš { a: 1 }

Piemēri

Izmantojot konstruktoru

Šis koda fragments ir ņemts no nodarbību parauga  un saglabāts tā oriģināls angļu valodā (tiešraides demonstrācija).
class Square extends Polygon {
constructor(length) {
// Here, it calls the parent class' constructor with lengths
// provided for the Polygon's width and height
super(length, length);
// NOTE: In derived classes, `super()` must be called before you
// can use `this`. Leaving this out will cause a ReferenceError.
this.name = "Square";
}

get area() {
return this.height * this.width;
}

set area(value) {
this.height = value ** 0.5;
this.width = value ** 0.5;
}
}

Izsaukšana super konstruktorā, kas saistīts ar citu prototipu
super() izsauc konstruktoru, kas ir pašreizējās klases prototips. Ja maināt pašas pašreizējās klases prototipu, super() izsauks jaunā prototipa konstruktoru. Pašreizējās klases prototipa rekvizīta prototipa maiņa neietekmē konstruktora super() izsaukumus.

class Poligons {
    constructor() {
      this.nosaukums = "Poligons";
    }
  }
 
  class Taisnstūris {
    constructor() {
      this.nosaukums = "Taisnstūris";
    }
  }
 
  class Kvadrāts extends Poligons {
    constructor() {
      super();
    }
  }
 
  // Izveido Kvadrāts kas izriet no Taisnstūris (kas ir bāzes klase) no klases Poligons
  Object.izveidotPrototipuNo(Kvadrāts, Taisnstūris);
 
  const jaunaInstance = new Kvadrāts();
 
  // jaunaInstance ir vēl aizvien instance no Poligons, jo mēs
  // nemainijām prototipu no Kvadrāts.prototype, tādēļ prototype ķēde
  // no jaunaInstance ir aizvien
  //   jaunaInstance --> Kvadrāts.prototype --> Poligons.prototype
  console.log(jaunaInstance instanceof Poligons); // true
  console.log(jaunaInstance instanceof Taisnstūris); // false
 
  // vēl aizvien super() izsauc Taisnstūris kā konstruktors, iekš nosaukums objekta
  //  jaunaInstance ir inicializēts ar loģiku iekš Taisnstūris
  console.log(jaunaInstance.nosaukums); // Taisnstūris
 

 

Loading

Noderīgs raksts? Dalies ar citiem: