რა ჯანდაბა არის this ჯავასკრიპტში?
this არის Javascript-ის ერთ-ერთი ყველაზე გაუგებარი კონცეფცია.
ჩემი გამოცდილებით, ეს ბუნდოვანება ძირითადად გამომდინარეობს this-ის კლასებთან ინტუიციურ კავშირთან.
სინამდვილეში, კლასები და this-იც ფუნდამენტურად განსხვავებულად მუშაობს ისეთ ე.წ. ობიექტზე ორიენტირებულ ენებთან შედარებით, როგორებიცაა: Java, C++, C# და ა.შ.
Javascript-ში this განისაზღვრება რამდენიმე ფაქტორის მიხედვით: ვიძახებთ თუ არა ფუნქციაში, რა ტიპის ფუნქციაში, რა კონტექსტში (scope), რომელ გარემოში და ა.შ.
განვიხილოთ ჩვეულებრივი, function keyword-ით შექმნილი ფუნქციები. შემდეგი 4 წესის დამახსოვრებით მარტივად შეგვეძლება this-ის მნიშვნელობის მიგნება:
- თუ ფუნქცია გამოიძახება new-ის გამოყენებით, მაშინ მეხსიერებაში გამოიყოფა ახალი ადგილი, გამოიძახება მითითებული ფუნქცია, რომელშიც this მიუთითებს ამ ახალ მეხსიერების ბლოკს;
- თუ ფუნქცია გამოიძახება call, apply ან bind-ის (ეს უკანასკნელი apply-ის ეყრდნობა) საშუალებით, მაშინ this განისაზღვრება ამ დამხმარე ფუნქციებში გადაცემული შესაბამის არგუმენტის მიხედვით;
- თუ ფუნქცია გამოიძახება რაიმე ობიექტზე (მეთოდად, ანუ obj.foo სტილში), მაშინ this მიუთითებს ამ ობიექტს;
- თუ არც ერთი ზემოთ ჩამოთვლილი პირობა არ შესრულდა, მაშინ this-ის მნიშვნელობა იქნება გლობალური ობიექტი (მკაცრ რეჟიმში — undefined).
აღსანიშნავია, რომ ჩამოთვლილი წესები იერარქიულადაა ჩამოთვლილი, ანუ რამდენიმე წესის თანხვედრით გამოყენებისას უპირატესობა მიენიჭება ზედა წესს.
მაგალითად, თუ ე.წ. hardbound ფუნქციას (bind-ით გამოყვანილ) new-ით გამოვიძახებთ, this მაინც ახალ ობიექტს დაუმიზნებს.
let testObj = { foo: 'this is a test object',
};function test() { return this;}console.log( new ( test.bind( testObj ) ) );
მარტივად გაგების მიზნით ზოგიერთი არასწორ პარალელს ავლებს ისრიან ფუნქციებსა და hardbound ფუნქციებს შორის.
ისრიანი ფუნქცია არაა hardbound ფუნქცია. ანუ მისი this არ განისაზღვრება runtime-ში დინამიური გამოძახებით ისე, როგორც bind-ის შემთხვევაში, არამედ ლექსიკური არეალის (lexical scope) მიხედვით.
ანუ, this ობიექტში მიუთითებს თავად ამ ობიექტს, გლობალურ scope-ში — window-ს, ან strict mode-ში undefined და ა.შ.
სხვათა შორის, Class-ის ტანში strict mode-ის პრინციპები მუშაობს, ამიტომ კლასის მეთოდში გამოცხადებული ფუნქციის პირდაპირ (მე-4 პირობის მიხედვით) გამოძახებაც this-ს undefined-ით განსაზღვრავს.
განვიხილოთ შემდეგი შემთხვევა:
რაიმე DOM ელემენტს onClick event handler-ად გავუწერთ რაღაც handleClick ფუნქციას:
ბრაუზერის ძრავის მუშაობის ფსევდო კოდი:
el.onclick = handleClick;el.onclick(); // <===== ‘this’-ის მნიშვნელობა განისაზღვრება ‘el’-ით
ამ შემთხვევაში this-ის მნიშვნელობა მიუთითებს თავად ამ DOM-ის ელემენტს, ვინაიდან, როგორც ჩანს, ბრაუზერის ძრავამ ამ ელემენტის გავლით გამოიძახა.
ბრაუზერს რომ ეს ფუნქცია სადმე ახალ ცვლადად დაემახსოვრებინა და ისე გამოეძახა, მაშინ this-ზე წვდომისას window ობიექტი დაგვიბრუნდებოდა:
var eventHandler = el.onclick;eventHandler; <===== ‘this’ მიუთითებდა ‘window’-ს
ბონუსად შეგიძლიათ იხილოთ React JS-ის event-ების მაგალითი:
იმედი მაქვს, ამ პოსტმა ნათელყო this-ის მუშაობის მექანიზმი. ამის შემდეგ თქვენ ნაკლებად დაგჭირდებათ თავის დასაზღვევად ისრიანი ფუნქციების ზედმეტად ხმარება. ჯავასკრიპტის ფუნქცია (function) მცოდნე ადამიანის ხელში ძლიერი იარაღია.
საკითხის კიდევ უფრო სიღრმისეულად შესასწავლად გირჩევდით Kyle Simpson-ის ვიდეოკურსებს Deep JavaScript Foundations, v3.
კომენტარებში შეგიძლიათ დაწეროთ ის თემები, რომელთა გარჩევასაც ისურვებდით.
გისურვებთ წარმატებებს, happy coding!