რა ჯანდაბა არის this ჯავასკრიპტში?

Konstantine Kutalia
2 min readNov 8, 2022

--

ის არა და მეორე ჯეკი ჩანის მიმი

this არის Javascript-ის ერთ-ერთი ყველაზე გაუგებარი კონცეფცია.

ჩემი გამოცდილებით, ეს ბუნდოვანება ძირითადად გამომდინარეობს this-ის კლასებთან ინტუიციურ კავშირთან.

სინამდვილეში, კლასები და this-იც ფუნდამენტურად განსხვავებულად მუშაობს ისეთ ე.წ. ობიექტზე ორიენტირებულ ენებთან შედარებით, როგორებიცაა: Java, C++, C# და ა.შ.

Javascript-ში this განისაზღვრება რამდენიმე ფაქტორის მიხედვით: ვიძახებთ თუ არა ფუნქციაში, რა ტიპის ფუნქციაში, რა კონტექსტში (scope), რომელ გარემოში და ა.შ.

განვიხილოთ ჩვეულებრივი, function keyword-ით შექმნილი ფუნქციები. შემდეგი 4 წესის დამახსოვრებით მარტივად შეგვეძლება this-ის მნიშვნელობის მიგნება:

  1. თუ ფუნქცია გამოიძახება new-ის გამოყენებით, მაშინ მეხსიერებაში გამოიყოფა ახალი ადგილი, გამოიძახება მითითებული ფუნქცია, რომელშიც this მიუთითებს ამ ახალ მეხსიერების ბლოკს;
  2. თუ ფუნქცია გამოიძახება call, apply ან bind-ის (ეს უკანასკნელი apply-ის ეყრდნობა) საშუალებით, მაშინ this განისაზღვრება ამ დამხმარე ფუნქციებში გადაცემული შესაბამის არგუმენტის მიხედვით;
  3. თუ ფუნქცია გამოიძახება რაიმე ობიექტზე (მეთოდად, ანუ obj.foo სტილში), მაშინ this მიუთითებს ამ ობიექტს;
  4. თუ არც ერთი ზემოთ ჩამოთვლილი პირობა არ შესრულდა, მაშინ 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!

--

--

Konstantine Kutalia

Aspiring software engineer specializing in front-end development and a guitar player.