VisaptveroÅ”s ceļvedis par JavaScript klaÅ”u mantoÅ”anu, kurÄ tiek apskatÄ«ti dažÄdi modeļi un labÄkÄs prakses stabilu un uzturamu lietojumprogrammu izveidei. ApgÅ«stiet klasiskÄs, prototipu un modernÄs mantoÅ”anas tehnikas.
JavaScript objektorientÄtÄ programmÄÅ”ana: Klases mantoÅ”anas modeļu apgūŔana
ObjektorientÄtÄ programmÄÅ”ana (OOP) ir spÄcÄ«ga paradigma, kas ļauj izstrÄdÄtÄjiem strukturÄt savu kodu modulÄrÄ un atkÄrtoti lietojamÄ veidÄ. MantoÅ”ana, kas ir OOP pamatkoncepcija, ļauj mums izveidot jaunas klases, pamatojoties uz esoÅ”ajÄm, pÄrmantojot to Ä«paŔības un metodes. Tas veicina koda atkÄrtotu izmantoÅ”anu, samazina dublÄÅ”anos un uzlabo uzturÄÅ”anu. JavaScript valodÄ mantoÅ”ana tiek panÄkta, izmantojot dažÄdus modeļus, katram no kuriem ir savas priekÅ”rocÄ«bas un trÅ«kumi. Å ajÄ rakstÄ tiek sniegts visaptveroÅ”s Å”o modeļu apskats, sÄkot no tradicionÄlÄs prototipu mantoÅ”anas lÄ«dz modernajÄm ES6 klasÄm un tÄlÄk.
Pamatu izpratne: Prototipi un prototipu Ä·Äde
SavÄ bÅ«tÄ«bÄ JavaScript mantoÅ”anas modelis balstÄs uz prototipiem. Katram JavaScript objektam ir piesaistÄ«ts prototipa objekts. Kad mÄÄ£inÄt piekļūt objekta Ä«paŔībai vai metodei, JavaScript vispirms to meklÄ tieÅ”i paÅ”Ä objektÄ. Ja to neizdodas atrast, tas meklÄ objekta prototipÄ. Å is process turpinÄs augÅ”up pa prototipu Ä·Ädi, lÄ«dz Ä«paŔība tiek atrasta vai tiek sasniegts Ä·Ädes gals (kas parasti ir `null`).
Å Ä« prototipu mantoÅ”ana atŔķiras no klasiskÄs mantoÅ”anas, kas sastopama tÄdÄs valodÄs kÄ Java vai C++. KlasiskajÄ mantoÅ”anÄ klases manto tieÅ”i no citÄm klasÄm. Prototipu mantoÅ”anÄ objekti manto tieÅ”i no citiem objektiem (vai, precÄ«zÄk, no prototipu objektiem, kas saistÄ«ti ar Å”iem objektiem).
`__proto__` īpaŔība (novecojusi, bet svarīga izpratnei)
Lai gan oficiÄli novecojusi, `__proto__` Ä«paŔība (divas apakÅ”svÄ«tras proto divas apakÅ”svÄ«tras) nodroÅ”ina tieÅ”u veidu, kÄ piekļūt objekta prototipam. Lai gan to nevajadzÄtu izmantot produkcijas kodÄ, tÄs izpratne palÄ«dz vizualizÄt prototipu Ä·Ädi. PiemÄram:
const animal = {
name: 'Generic Animal',
makeSound: function() {
console.log('Generic sound');
}
};
const dog = {
name: 'Dog',
breed: 'Golden Retriever'
};
dog.__proto__ = animal; // Sets animal as the prototype of dog
console.log(dog.name); // Output: Dog (dog has its own name property)
console.log(dog.breed); // Output: Golden Retriever
console.log(dog.makeSound()); // Output: Generic sound (inherited from animal)
Å ajÄ piemÄrÄ `dog` manto `makeSound` metodi no `animal` caur prototipu Ä·Ädi.
`Object.getPrototypeOf()` un `Object.setPrototypeOf()` metodes
Å Ä«s ir ieteicamÄs metodes, lai attiecÄ«gi iegÅ«tu un iestatÄ«tu objekta prototipu, piedÄvÄjot standartizÄtÄku un uzticamÄku pieeju salÄ«dzinÄjumÄ ar `__proto__`. Apsveriet Å”o metožu izmantoÅ”anu prototipu attiecÄ«bu pÄrvaldīŔanai.
const animal = {
name: 'Generic Animal',
makeSound: function() {
console.log('Generic sound');
}
};
const dog = {
name: 'Dog',
breed: 'Golden Retriever'
};
Object.setPrototypeOf(dog, animal);
console.log(dog.name); // Output: Dog
console.log(dog.breed); // Output: Golden Retriever
console.log(dog.makeSound()); // Output: Generic sound
console.log(Object.getPrototypeOf(dog) === animal); // Output: true
KlasiskÄs mantoÅ”anas simulÄcija ar prototipiem
Lai gan JavaScript nav klasiskÄs mantoÅ”anas tÄdÄ paÅ”Ä veidÄ kÄ dažÄs citÄs valodÄs, mÄs to varam simulÄt, izmantojot konstruktora funkcijas un prototipus. Å Ä« pieeja bija izplatÄ«ta pirms ES6 klaÅ”u ievieÅ”anas.
Konstruktora funkcijas
Konstruktora funkcijas ir parastas JavaScript funkcijas, kuras tiek izsauktas, izmantojot `new` atslÄgvÄrdu. Kad konstruktora funkcija tiek izsaukta ar `new`, tÄ izveido jaunu objektu, iestata `this`, lai tas atsauktos uz Å”o objektu, un netieÅ”i atgriež jauno objektu. Konstruktora funkcijas `prototype` Ä«paŔība tiek izmantota, lai definÄtu jaunÄ objekta prototipu.
function Animal(name) {
this.name = name;
}
Animal.prototype.makeSound = function() {
console.log('Generic sound');
};
function Dog(name, breed) {
Animal.call(this, name); // Call the Animal constructor to initialize the name property
this.breed = breed;
}
// Set Dog's prototype to a new instance of Animal. This establishes the inheritance link.
Dog.prototype = Object.create(Animal.prototype);
// Correct the constructor property on Dog's prototype to point to Dog itself.
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log('Woof!');
};
const myDog = new Dog('Buddy', 'Labrador');
console.log(myDog.name); // Output: Buddy
console.log(myDog.breed); // Output: Labrador
console.log(myDog.makeSound()); // Output: Generic sound (inherited from Animal)
console.log(myDog.bark()); // Output: Woof!
console.log(myDog instanceof Animal); // Output: true
console.log(myDog instanceof Dog); // Output: true
Paskaidrojums:
- `Animal.call(this, name)`: Å Ä« rinda izsauc `Animal` konstruktoru `Dog` konstruktora ietvaros, iestatot `name` Ä«paŔību jaunajam `Dog` objektam. TÄ mÄs inicializÄjam vecÄkklasÄ definÄtÄs Ä«paŔības. `.call` metode ļauj mums izsaukt funkciju ar konkrÄtu `this` kontekstu.
- `Dog.prototype = Object.create(Animal.prototype)`: Å is ir mantoÅ”anas iestatīŔanas kodols. `Object.create(Animal.prototype)` izveido jaunu objektu, kura prototips ir `Animal.prototype`. PÄc tam mÄs pieŔķiram Å”o jauno objektu `Dog.prototype`. Tas izveido mantoÅ”anas attiecÄ«bu: `Dog` instances mantos Ä«paŔības un metodes no `Animal` prototipa.
- `Dog.prototype.constructor = Dog`: PÄc prototipa iestatīŔanas `constructor` Ä«paŔība `Dog.prototype` nepareizi norÄdÄ«s uz `Animal`. Mums tas ir jÄatiestata, lai tas norÄdÄ«tu uz paÅ”u `Dog`. Tas ir svarÄ«gi, lai pareizi identificÄtu `Dog` instanÄu konstruktoru.
- `instanceof`: `instanceof` operators pÄrbauda, vai objekts ir noteiktas konstruktora funkcijas (vai tÄs prototipu Ä·Ädes) instance.
KÄpÄc `Object.create`?
`Object.create(Animal.prototype)` izmantoÅ”ana ir bÅ«tiska, jo tÄ izveido jaunu objektu, neizsaucot `Animal` konstruktoru. Ja mÄs izmantotu `new Animal()`, mÄs netīŔi izveidotu `Animal` instanci kÄ daļu no mantoÅ”anas iestatīŔanas, kas nav tas, ko mÄs vÄlamies. `Object.create` nodroÅ”ina tÄ«ru veidu, kÄ izveidot prototipu saikni bez nevÄlamiem blakusefektiem.
ES6 klases: Sintaktiskais cukurs prototipu mantoŔanai
ES6 (ECMAScript 2015) ieviesa `class` atslÄgvÄrdu, nodroÅ”inot pazÄ«stamÄku sintaksi klaÅ”u definÄÅ”anai un mantoÅ”anai. TomÄr ir svarÄ«gi atcerÄties, ka ES6 klases joprojÄm pamatÄ balstÄs uz prototipu mantoÅ”anu. TÄs nodroÅ”ina ÄrtÄku un lasÄmÄku veidu, kÄ strÄdÄt ar prototipiem.
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log('Generic sound');
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call the Animal constructor
this.breed = breed;
}
bark() {
console.log('Woof!');
}
}
const myDog = new Dog('Buddy', 'Labrador');
console.log(myDog.name); // Output: Buddy
console.log(myDog.breed); // Output: Labrador
console.log(myDog.makeSound()); // Output: Generic sound
console.log(myDog.bark()); // Output: Woof!
console.log(myDog instanceof Animal); // Output: true
console.log(myDog instanceof Dog); // Output: true
Paskaidrojums:
- `class Animal { ... }`: DefinÄ klasi ar nosaukumu `Animal`.
- `constructor(name) { ... }`: DefinÄ `Animal` klases konstruktoru.
- `extends Animal`: NorÄda, ka `Dog` klase manto no `Animal` klases.
- `super(name)`: Izsauc vecÄkklases (`Animal`) konstruktoru, lai inicializÄtu `name` Ä«paŔību. `super()` ir jÄizsauc pirms piekļuves `this` atvasinÄtÄs klases konstruktorÄ.
ES6 klases nodroÅ”ina tÄ«rÄku un kodolÄ«gÄku sintaksi objektu izveidei un mantoÅ”anas attiecÄ«bu pÄrvaldīŔanai, padarot kodu vieglÄk lasÄmu un uzturamu. `extends` atslÄgvÄrds vienkÄrÅ”o apakÅ”klaÅ”u izveides procesu, un `super()` atslÄgvÄrds nodroÅ”ina vienkÄrÅ”u veidu, kÄ izsaukt vecÄkklases konstruktoru un metodes.
Metodes pÄrrakstīŔana
Gan klasiskÄ simulÄcija, gan ES6 klases ļauj pÄrrakstÄ«t metodes, kas mantotas no vecÄkklases. Tas nozÄ«mÄ, ka jÅ«s varat nodroÅ”inÄt specializÄtu metodes implementÄciju bÄrnklasÄ.
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log('Generic sound');
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
makeSound() {
console.log('Woof!'); // Overriding the makeSound method
}
bark() {
console.log('Woof!');
}
}
const myDog = new Dog('Buddy', 'Labrador');
myDog.makeSound(); // Output: Woof! (Dog's implementation)
Å ajÄ piemÄrÄ `Dog` klase pÄrraksta `makeSound` metodi, nodroÅ”inot savu implementÄciju, kas izvada "Woof!".
Ärpus klasiskÄs mantoÅ”anas: AlternatÄ«vi modeļi
Lai gan klasiskÄ mantoÅ”ana ir izplatÄ«ts modelis, tas ne vienmÄr ir labÄkais risinÄjums. Dažos gadÄ«jumos alternatÄ«vi modeļi, piemÄram, miksÄ«ni un kompozÄ«cija, piedÄvÄ lielÄku elastÄ«bu un ļauj izvairÄ«ties no iespÄjamÄm mantoÅ”anas kļūmÄm.
Miksīni
MiksÄ«ni ir veids, kÄ pievienot funkcionalitÄti klasei, neizmantojot mantoÅ”anu. MiksÄ«ns ir klase vai objekts, kas nodroÅ”ina metožu kopu, ko var "iemaisÄ«t" citÄs klasÄs. Tas ļauj atkÄrtoti izmantot kodu vairÄkÄs klasÄs, neveidojot sarežģītu mantoÅ”anas hierarhiju.
const barkMixin = {
bark() {
console.log('Woof!');
}
};
const flyMixin = {
fly() {
console.log('Flying!');
}
};
class Dog {
constructor(name) {
this.name = name;
}
}
class Bird {
constructor(name) {
this.name = name;
}
}
// Apply the mixins (using Object.assign for simplicity)
Object.assign(Dog.prototype, barkMixin);
Object.assign(Bird.prototype, flyMixin);
const myDog = new Dog('Buddy');
myDog.bark(); // Output: Woof!
const myBird = new Bird('Tweety');
myBird.fly(); // Output: Flying!
Å ajÄ piemÄrÄ `barkMixin` nodroÅ”ina `bark` metodi, kas tiek pievienota `Dog` klasei, izmantojot `Object.assign`. LÄ«dzÄ«gi `flyMixin` nodroÅ”ina `fly` metodi, kas tiek pievienota `Bird` klasei. Tas ļauj abÄm klasÄm iegÅ«t vÄlamo funkcionalitÄti, nebÅ«damas saistÄ«tas caur mantoÅ”anu.
SarežģītÄkas miksÄ«nu implementÄcijas varÄtu izmantot rÅ«pnÄ«cfunkcijas vai dekoratorus, lai nodroÅ”inÄtu lielÄku kontroli pÄr iemaisīŔanas procesu.
Kompozīcija
KompozÄ«cija ir vÄl viena alternatÄ«va mantoÅ”anai. TÄ vietÄ, lai mantotu funkcionalitÄti no vecÄkklases, klase var saturÄt citu klaÅ”u instances kÄ komponentus. Tas ļauj veidot sarežģītus objektus, kombinÄjot vienkÄrÅ”Äkus objektus.
class Engine {
start() {
console.log('Engine started');
}
}
class Wheels {
rotate() {
console.log('Wheels rotating');
}
}
class Car {
constructor() {
this.engine = new Engine();
this.wheels = new Wheels();
}
drive() {
this.engine.start();
this.wheels.rotate();
console.log('Car driving');
}
}
const myCar = new Car();
myCar.drive();
// Output:
// Engine started
// Wheels rotating
// Car driving
Å ajÄ piemÄrÄ `Car` klase sastÄv no `Engine` un `Wheels`. TÄ vietÄ, lai mantotu no Ŕīm klasÄm, `Car` klase satur to instances un izmanto to metodes, lai Ä«stenotu savu funkcionalitÄti. Å Ä« pieeja veicina vÄju sasaisti un nodroÅ”ina lielÄku elastÄ«bu, kombinÄjot dažÄdus komponentus.
LabÄkÄs prakses JavaScript mantoÅ”anai
- PriekÅ”roku dodiet kompozÄ«cijai, nevis mantoÅ”anai: Kad vien iespÄjams, dodiet priekÅ”roku kompozÄ«cijai, nevis mantoÅ”anai. KompozÄ«cija piedÄvÄ lielÄku elastÄ«bu un ļauj izvairÄ«ties no cieÅ”Äs sasaistes, kas var rasties mantoÅ”anas hierarhijÄs.
- Izmantojiet ES6 klases: Izmantojiet ES6 klases tÄ«rÄkai un lasÄmÄkai sintaksei. TÄs nodroÅ”ina modernÄku un uzturamÄku veidu, kÄ strÄdÄt ar prototipu mantoÅ”anu.
- Izvairieties no dziļÄm mantoÅ”anas hierarhijÄm: Dziļas mantoÅ”anas hierarhijas var kļūt sarežģītas un grÅ«ti saprotamas. Uzturiet mantoÅ”anas hierarhijas seklas un fokusÄtas.
- Apsveriet miksÄ«nus: Izmantojiet miksÄ«nus, lai pievienotu funkcionalitÄti klasÄm, neveidojot sarežģītas mantoÅ”anas attiecÄ«bas.
- Izprotiet prototipu Ä·Ädi: Stabila prototipu Ä·Ädes izpratne ir bÅ«tiska, lai efektÄ«vi strÄdÄtu ar JavaScript mantoÅ”anu.
- Pareizi izmantojiet `Object.create`: SimulÄjot klasisko mantoÅ”anu, izmantojiet `Object.create(Parent.prototype)`, lai izveidotu prototipu attiecÄ«bu, neizsaucot vecÄkklases konstruktoru.
- KoriÄ£Äjiet konstruktora Ä«paŔību: PÄc prototipa iestatīŔanas koriÄ£Äjiet `constructor` Ä«paŔību bÄrnklases prototipÄ, lai tas norÄdÄ«tu uz bÄrnklases konstruktoru.
GlobÄli apsvÄrumi par koda stilu
StrÄdÄjot globÄlÄ komandÄ, Åemiet vÄrÄ Å”Ädus punktus:
- Konsekventas nosaukumu pieŔķirÅ”anas konvencijas: Izmantojiet skaidras un konsekventas nosaukumu pieŔķirÅ”anas konvencijas, kuras ir viegli saprotamas visiem komandas locekļiem, neatkarÄ«gi no viÅu dzimtÄs valodas.
- Koda komentÄri: Rakstiet visaptveroÅ”us koda komentÄrus, lai izskaidrotu sava koda mÄrÄ·i un funkcionalitÄti. Tas ir Ä«paÅ”i svarÄ«gi sarežģītÄm mantoÅ”anas attiecÄ«bÄm. Apsveriet iespÄju izmantot dokumentÄcijas Ä£eneratoru, piemÄram, JSDoc, lai izveidotu API dokumentÄciju.
- InternacionalizÄcija (i18n) un lokalizÄcija (l10n): Ja jÅ«su lietojumprogrammai jÄatbalsta vairÄkas valodas, apsveriet, kÄ mantoÅ”ana varÄtu ietekmÄt jÅ«su i18n un l10n stratÄÄ£ijas. PiemÄram, jums varÄtu nÄkties pÄrrakstÄ«t metodes apakÅ”klasÄs, lai apstrÄdÄtu dažÄdas valodai specifiskas formatÄÅ”anas prasÄ«bas.
- TestÄÅ”ana: Rakstiet rÅ«pÄ«gus vienÄ«btestus, lai nodroÅ”inÄtu, ka jÅ«su mantoÅ”anas attiecÄ«bas darbojas pareizi un ka visas pÄrrakstÄ«tÄs metodes darbojas kÄ paredzÄts. PievÄrsiet uzmanÄ«bu robežgadÄ«jumu un iespÄjamo veiktspÄjas problÄmu testÄÅ”anai.
- Koda pÄrskatīŔana: Veiciet regulÄras koda pÄrskatīŔanas, lai nodroÅ”inÄtu, ka visi komandas locekļi ievÄro labÄkÄs prakses un ka kods ir labi dokumentÄts un viegli saprotams.
Nobeigums
JavaScript mantoÅ”ana ir spÄcÄ«gs rÄ«ks atkÄrtoti lietojama un uzturama koda veidoÅ”anai. Izprotot dažÄdus mantoÅ”anas modeļus un labÄkÄs prakses, jÅ«s varat izveidot stabilas un mÄrogojamas lietojumprogrammas. NeatkarÄ«gi no tÄ, vai izvÄlaties izmantot klasisko simulÄciju, ES6 klases, miksÄ«nus vai kompozÄ«ciju, galvenais ir izvÄlÄties modeli, kas vislabÄk atbilst jÅ«su vajadzÄ«bÄm, un rakstÄ«t kodu, kas ir skaidrs, kodolÄ«gs un viegli saprotams globÄlai auditorijai.