OOP & Prototypes (ES5)
"JavaScript-ը պրոտոտիպային լեզու է։ Հասկանալով պրոտոտիպերը՝ դուք տիրապետում եք լեզվի հիմքին։"
Ինչ է Prototype-ը:
JavaScript-ում ամեն օբյեկտ ունի հատուկ թաքնված հատկություն՝
[[Prototype]], որը կա՛մ null է, կա՛մ հղում է
մեկ այլ օբյեկտի։ Այդ օբյեկտը կոչվում է
"prototype" (նախատիպ)։
Գաղափարը
Եթե մենք փորձում ենք կարդալ մի հատկություն (property), որը չկա օբյեկտի մեջ, JS-ը ավտոմատ այն փնտրում է իր prototype-ի մեջ։
F.prototype (Ֆունկցիայի նախատիպ)
Երբ մենք ստեղծում ենք օբյեկտ կոնստրուկտոր ֆունկցիայի միջոցով
new F(), նոր ստեղծված օբյեկտի
[[Prototype]]-ը դառնում է այն օբյեկտը, որին հղվում է
F.prototype-ը։
Օրինակ
function
Animal(name) {this.name =
name;}
// Ավելացնում ենք մեթոդ նախատիպի մեջ
Animal.prototype.eat
= function() {console.log(this.name +
" is eating...");};
let rabbit =
new
Animal("White Rabbit");rabbit.eat();
// "White Rabbit is eating..."
Կարևոր է
Animal.prototype-ը սովորական օբյեկտ է, որն
ունի մեկ նախնական հատկություն՝ constructor, որը
հղվում է հենց ֆունկցիայի վրա։
Ինչու՞ օգտագործել Prototype մեթոդների համար:
Պատկերացրեք՝ ունեք 1000 հատ Animal օբյեկտ։
❌ Առանց Prototype
Եթե մեթոդը սահմանեք
this.eat = function... կոնստրուկտորի ներսում,
ամեն մի օբյեկտի հետ կստեղծվի նոր ֆունկցիա (հիշողության
վատնում)։
✅ Prototype-ով
Ֆունկցիան ստեղծվում է մեկ անգամ
Animal.prototype-ում, և բոլոր 1000 օբյեկտները
հղվում են նույն ֆունկցիայի վրա։
Ժառանգություն (Prototypal Inheritance)
Ժառանգությունը JavaScript-ում հիմնված է Prototypal Delegation-ի (Նախատիպային պատվիրակման) վրա: Օբյեկտը «պատվիրակում» է իր հարցումները ծնողին, երբ իր մոտ չի գտնում համապատասխան հատկությունը:
1. Կոնստրուկտորի կանչ (Constructor Stealing)
function
Animal(name) {this.name =
name;}
function
Rabbit(name, speed) {// Կանչում ենք ծնողին այս (this) օբյեկտի համար
Animal.call(this, name); this.speed =
speed;}
2. Prototype Chain-ի կառուցում
Rabbit.prototype =
Object.create(Animal.prototype);// Վերականգնում ենք constructor-ը
Rabbit.prototype.constructor =
Rabbit;
3. Մեթոդների ավելացում և Override
Animal.prototype.move
= function() {console.log(this.name + " is moving.");};
// Override (Գերազանցում)
Rabbit.prototype.move
= function() {console.log(this.name + " hops fast!");};
Ինչպե՞ս է JS-ը փնտրում հատկությունը
Երբ դուք կանչում եք bugsy.move(), տեղի է
ունենում հետևյալը.
- 1. Search in bugsy: Կա՞ արդյոք move մեթոդը հենց օբյեկտի մեջ: (Ոչ):
- 2. Search in Rabbit.prototype: JS-ը բարձրանում է վերև: Կա՞ այստեղ move: (Այո):
- 3. Search in Animal.prototype: Եթե նախորդում չլիներ, նա կբարձրանար այստեղ:
- 4. Object.prototype: Վերջին կանգառը:
⚠️ Հաճախակի տրվող հարց
Ինչու՞ չօգտագործել
Rabbit.prototype = new Animal():
Սա վատ պրակտիկա է, որովհետև new Animal()-ը
ստեղծում է Animal-ի հատկություններ (օրինակ՝
name: undefined) հենց Prototype-ի մեջ:
Object.create-ը ստեղծում է «մաքուր» կապ առանց
ծնողի կոնստրուկտորը կանչելու:
__proto__ vs prototype
prototype-ը հատկություն է, որը կա միայն ֆունկցիաների
մեջ։
[[Prototype]]-ը (կամ __proto__-ն) հղում է,
որը կա բոլոր օբյեկտների մեջ։
Performance & Native
Բոլոր ներկառուցված օբյեկտները (Array, Date) ունեն իրենց
նախատիպերը։
Օգտագործեք obj.hasOwnProperty(key) միայն սեփական
հատկությունները ստուգելու համար։