Skip to content

Latest commit

 

History

History
59 lines (41 loc) · 6.78 KB

Advanced Functional Patterns.hy.md

File metadata and controls

59 lines (41 loc) · 6.78 KB

Ֆունկցիաների շաղկապումը կոնտեքստի հետ՝ bind մեթոդի օգնությամբ:

Մենք գիտենք, որ JavaScript ծրագրավորման լեզվում this-ի արժեքը որոշվում է ոչ թե ֆունկցիայի ստեղծման՝ այլ կանչի ժամանակ: Այս առանձնահատկության շնորհիվ JavaScript-ը տարբերվում է մի շարք այլ դասական ծրագրավորման լեզուներից։ Նաև ծանոթ ենք, որ JavaScript-ում ֆունկցիաները հանդիսանում են օբյեկտներ, որոնք ինչ-որ գործողություն են կատարում, և կարող են ունենալ հատկություններ՝ ինչպես սովորական օբյեկտների դեպքում էր։ Իսկ եթե ֆունկցիաները հանդիսանում են օբյեկտներ և ունեն հատկություններ, նրանք կարող են ունենալ նաև մեթոդներ։ Ծանոթանանք ֆունկցիաների ներդրված մեթոդներից մեկի՝ bind-ի հետ, որը հիմնականում օգտագործվում է this-ը ֆունկցիայի հետ շաղկապելու համար (Ի՞նչու հիմնականում, որովհետև այլ կիրառություն նույնպես ունի՝ երբեմն bind-ի օգնությամբ ստեղծում են ֆիքսված արգումենտներով ֆունկցիաներ)։ Մինչ bind մեթոդին ծանոթանալը՝ կարդացեք this-ի և ֆունկցիաների օբյեկտներ հանդիսանալու մասին:

this-ին նվիրված գրառման մեջ մենք արդեն տեսել ենք JavaScript-ում ազատ this-ի կոնցեպտի «տարօրինակ» հետևանքները։

"use strict";

const person = {
  firstName: "John",
  lastName: "Smith",
  sayHello: function () {
    alert("hello " + this.firstName + " " + this.lastName);
  },
};

person.sayHello(); // hello John Smith

Ունենք person օբյեկտը, որի մեջ գտնվող sayHello մեթոդի կանչը alert է անում person-ին ուղղված ողջույնի խոսքը։ Ինչպես գիտենք մեթոդի սինթաքսը օգտագործելու ժամանակ this-ի արժեքը միշտ լինում է կետից առաջ գտնվող օբյեկտը։ Սակայն եթե այժմ մենք person օբյեկտի sayHello մեթոդը վերագրենք մեկ այլ փոփոխականի և փորձենք կանչել այդ փոփոխականի օգնությամբ, this-ի արժեքը այլևս չի լինի person օբյեկտը։ Այսինքն չնայած, որ sayHello մեթոդը ստեղծվել է person օբյեկտի մեջ և պատկանում է person օբյեկտին, դա ոչ մի երաշխիք չի տալիս մեզ, որ this-ի արժեքը միշտ լինելու է person օբյեկտը։

"use strict";
const greeting = person.sayHello;
greeting(); // Uncaught TypeError

Ինչպես տեսնում ենք greeting ֆունկցիայի կանչը առաջացնում է սխալ։ Երբ կոնսոլում կարդում ենք սխալի նկարագրությունը՝ տեսնում ենք սխալն առաջացել է, որովհետև this-ի արժեքը undefined է։ Որպեսզի this-ի արժեքը միշտ հղվի այն օբյեկտին, որի մեջ ստեղծվել է մեթոդը, մենք կարող ենք օգտագործել ֆունկցիաների bind մեթոդը։

const greeting = person.sayHello.bind(person);
greeting(); // hello John Smith

Մենք person օբյեկտի sayHello մեթոդի վրա ֆունկցիաների bind մեթոդի օգնությամբ ֆիքսում ենք person օբյեկտը որպես this-ի արժեք։ Այն վերադարձնում է նոր ֆունկցիա՝ greeting-ը, որի կանչը միշտ վերահասցեավորվում է sayHello մեթոդի կանչին՝ person օբյեկտի կոնտեքստում։

Պետք է հիշել, որ բոլոր այն դեպքերում, երբ մեթոդն անմիջապես օբյեկտի վրայից չի կանչվում, տեղի է ունենում this-ի կորուստ։ Քննարկենք մեկ այլ իրադրություն, երբ օբյեկտի մեթոդն օգտագործվում է որպես հետադարձ կանչի ֆունկցիա, այսինքն որպես արգումենտ տրվում է մեկ այլ ֆունկցիայի։ Օրինակ փորձենք օբյեկտի մեթոդը որպես արգումենտ հաղորդել setTimeout ֆունկցիային։

setTimeout(person.sayHello, 1000);

Աշխատեցնելով կոդը, մի վայրկայնից alert-ի պատուհանում կտեսնենք hello undefined undefined արտահայտությունը։ Այսինքն person.sayHello մեթոդն այլևս չի հղվում person օբյեկտին։ Այն ճիշտ է՝ ստեղծվել է person օբյեկտի մեջ, բայց նրա this-ի արժեքը այժմ person-ը չէ, որովհետև նրա կանչը տեղի է ունենում գլոբալ կոնտեքստում և հետևաբար նրա this-ը այժմ անորոշ է՝ undefined (Ոչ խիստ ռեժիմում՝ window կամ Object [global] կախված միջավայրից

Այժմ փորձենք bind մեթոդի օգնությամբ person օբյեկտը ֆիքսել, շաղկապել sayHello մեթոդի վրա, որպեսզի setTimeout ֆունկցիայի կանչը վերադարձնի կոռեկտ արդյունք։

setTimeout(person.sayHello.bind(person), 1000);

Աշխատեցնելով կոդը, մի վայրկյանից alert-ի պատուհանում կտեսնենք hello John Smith: Որպեսզի կոդն ավելի պարզ և ընթեռնելի դարձնենք, մենք կարող ենք վերևի արտահայտությունը կիսել երկու մասի՝ շաղկապած (կամ բայնդինգ արած) մեթոդը վերագրելով ուրիշ փոփոխականի, և ապա նոր որպես արգումենտ հաղորդելով setTimeout ֆունկցիային։

const sayHello = person.sayHello.bind(person);
setTimeout(sayHello, 1000); // hello John Smith

Ի դեպ bind մեթոդը JavaScript-ում առկա է դեռևս ES5 ստանդարտի ժամանակներից և հասկանալի է բոլոր ժամանակակից ցանցային դիտարկիչներին (նույնիսկ Internet Explorer-ին՝ սկսած 9-րդ տարբերակից