JavaScript'ning 'this' kalit so'zini tushuntirish, an'anaviy funksiyalarda kontekst o'zgarishini o'rganish va global dasturchilar uchun strela funksiyalari bashoratlilik xulqini tushunish.
JavaScript 'this' Bog'lanishi: Kontekst O'zgarishi vs. Strela Funksiyalari Xulqi
JavaScript 'this' kalit so'zi tilning eng kuchli, ammo ko'pincha noto'g'ri tushuniladigan xususiyatlaridan biridir. Uning xulqi, ayniqsa JavaScriptga yangi kirganlar yoki qat'iyroq doira qoidalariga o'rganganlar uchun chalkashlik manbai bo'lishi mumkin. Eng asosi, 'this' funksiya ijro etilayotgan kontekstga ishora qiladi. Bu kontekst dinamik ravishda o'zgarishi mumkin, bu esa ko'pincha 'kontekst o'zgarishi' deb ataladi. 'this' qanday va nima uchun o'zgarishini tushunish mustahkam va bashoratlilik JavaScript kodini yozish uchun, ayniqsa murakkab ilovalarda va global jamoa bilan hamkorlikda muhimdir. Ushbu maqolada an'anaviy JavaScript funksiyalarida 'this' bog'lanishining murakkabliklari, uni strela funksiyalari xulqi bilan solishtirish va dunyodagi dasturchilar uchun amaliy tushunchalar berish ko'rib chiqiladi.
JavaScriptda 'this' Kalit So'zini Tushunish
'this' - bu kodni hozirda ijro etayotgan ob'ektga havoladir. 'this' qiymati funksiyaning qanday chaqirilishiga qarab belgilanadi, na funksiyaning qayerda aniqlanganligiga qarab. Ushbu dinamik bog'lanish 'this'ni shunchalik moslashuvchan qiladi, ammo umumiy tuzoq hamdir. Standart funksiyalarda 'this' bog'lanishiga ta'sir qiluvchi turli vaziyatlarni ko'rib chiqamiz.
1. Global Kontekst
'this' har qanday funksiyadan tashqarida ishlatilganda, u global ob'ektga ishora qiladi. Brauzer muhitida global ob'ekt window
hisoblanadi. Node.js da esa global
.
// Brauzer muhitida
console.log(this === window); // true
// Node.js muhitida
// console.log(this === global); // true (yuqori darajali doirada)
Global Nuqtai Nazar: window
brauzerlarga xos bo'lsa-da, global ob'ekt konsepsiyasi, unga 'this' eng yuqori darajadagi doirada ishora qiladi, turli JavaScript muhitlarida haqiqat bo'lib qoladi. Bu JavaScript ijro kontekstining asosiy jihatidir.
2. Metodni Chaqirish
Biror funksiya ob'ekt metodi sifatida chaqirilganda (nuqta yoki qavslar orqali), ushbu funksiya ichidagi 'this' uslub chaqirilgan ob'ektga ishora qiladi.
const person = {
name: "Alice",
greet: function() {
console.log(`Salom, mening ismim ${this.name}`);
}
};
person.greet(); // Natija: Salom, mening ismim Alice
Ushbu misolda, greet
person
ob'ekti ustida chaqirilgan. Shu sababli, greet
ichida 'this' person
ga ishora qiladi va this.name
to'g'ri "Alice"ni oladi.
3. Konstruktor Chaqiruvi
Biror funksiya new
kalit so'zi bilan konstruktor sifatida ishlatilganda, konstruktor ichidagi 'this' ob'ektning yangi yaratilgan namunasi bilan ishora qiladi.
function Car(make, model) {
this.make = make;
this.model = model;
this.displayInfo = function() {
console.log(`Bu mashina ${this.make} ${this.model} dir`);
};
}
const myCar = new Car("Toyota", "Corolla");
myCar.displayInfo(); // Natija: Bu mashina Toyota Corolla dir
Bu yerda, new Car(...)
yangi ob'ekt yaratadi va Car
funksiyasi ichidagi 'this' ushbu yangi ob'ektga ishora qiladi. make
va model
xususiyatlari unga beriladi.
4. Oddiy Funksiya Chaqiruvi (Kontekst O'zgarishi)
Bu yerda chalkashlik ko'pincha boshlanadi. Biror funksiya to'g'ridan-to'g'ri, metod yoki konstruktor sifatida chaqirilmaganda, uning 'this' bog'lanishi murakkab bo'lishi mumkin. Qat'iy bo'lmagan rejimda, 'this' standart bo'lib global ob'ektga (window
yoki global
) bog'lanadi. Qat'iy rejimda ('use strict';), 'this' undefined
bo'ladi.
function showThis() {
console.log(this);
}
// Qat'iy bo'lmagan rejim:
showThis(); // Brauzerda: window ob'ektiga ishora qiladi
// Qat'iy rejim:
'use strict';
function showThisStrict() {
console.log(this);
}
showThisStrict(); // undefined
Global Nuqtai Nazar: Qat'iy va qat'iy bo'lmagan rejim o'rtasidagi farq global miqyosda juda muhimdir. Ko'pgina zamonaviy JavaScript loyihalari standart bo'yicha qat'iy rejimi qo'llaydi, bu esa oddiy funksiya qo'ng'iroqlari uchun undefined
xulqi eng keng tarqalgan holat bo'lib qoladi. Ushbu muhit sozlamasini bilish muhimdir.
5. Hodisa Tinglovchilari
Brauzer muhitlarida, biror funksiya hodisa tinglovchisi sifatida ishlatilganda, 'this' odatda hodisani keltirib chiqargan DOM elementiga ishora qiladi.
// HTML elementini taxmin qilib:
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this); // 'this' tugmaga ishora qiladi
this.textContent = "Bosildi!";
});
Global Nuqtai Nazar: DOM manipulyatsiyasi brauzerga xos bo'lsa-da, 'this' ning hodisani chaqirgan elementga bog'lanishining asosiy printsipi turli platformalarda hodisa-yo'naltirilgan dasturlashda keng tarqalgan namuna hisoblanadi.
6. Call, Apply va Bind
JavaScript funksiyani chaqirishda 'this' qiymatini aniq belgilash usullarini taqdim etadi:
call()
: Ma'lum bir 'this' qiymati va individual ravishda taqdim etilgan argumentlar bilan funksiyani chaqiradi.apply()
: Ma'lum bir 'this' qiymati va massiv sifatida taqdim etilgan argumentlar bilan funksiyani chaqiradi.bind()
: Yangi funksiya yaratadi, uni chaqirganda, u qanday chaqirilishidan qat'iy nazar, o'zining 'this' kalit so'zini berilgan qiymatga o'rnatadi.
const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // undefined (qat'iy rejimda) yoki xatolik (qat'iy bo'lmagan rejimda)
// 'this'ni aniq belgilash uchun calldan foydalanish
const boundGetXCall = unboundGetX.call(module);
console.log(boundGetXCall); // 42
// applydan foydalanish (argumentlar massiv sifatida, bu yerda tegishli emas, lekin sintaksini ko'rsatadi)
const boundGetXApply = unboundGetX.apply(module);
console.log(boundGetXApply); // 42
// 'this'ni doimiy bog'langan yangi funksiya yaratish uchun binddan foydalanish
const boundGetXBind = unboundGetX.bind(module);
console.log(boundGetXBind()); // 42
bind()
, ayniqsa, muvaffaqiyatsiz operatsiyalar yoki qayta chaqiruvlar sifatida funksiyalarni uzatganda, to'g'ri 'this' kontekstini saqlab qolish uchun juda foydalidir. Bu aniq kontekstni boshqarish uchun kuchli vositadir.
Qayta Chaqiruv Funksiyalarida 'this' Muammosi
'this' bog'lanish muammolarining eng keng tarqalgan manbalaridan biri, ayniqsa setTimeout
, hodisa tinglovchilari yoki tarmoq so'rovlari kabi muvaffaqiyatsiz operatsiyalar ichidagi qayta chaqiruv funksiyalari bilan yuzaga keladi. Chunki qayta chaqiruv keyinroq va boshqa kontekstda ijro etiladi, uning 'this' qiymati ko'pincha kutilgan narsadan farq qiladi.
function Timer() {
this.seconds = 0;
setInterval(function() {
// Bu yerdagi 'this' global ob'ektga (yoki qat'iy rejimda undefinedga) ishora qiladi
// Timer misoliga emas!
this.seconds += 1;
console.log(this.seconds);
}, 1000);
}
// const timer = new Timer(); // Bu katta ehtimol bilan xatoliklarga yoki kutilmagan natijalarga olib keladi.
Yuqoridagi misolda, setInterval
ga uzatilgan funksiya oddiy funksiya chaqiruvi bo'lib, shuning uchun uning 'this' konteksti yo'qoladi. Bu global ob'ekt ustida (yoki undefined
) xususiyatni oshirishga olib keladi, bu esa niyat emas.
Qayta Chaqiruv Kontekst Muammolarini Yechish
Tarixan, dasturchilar bir nechta yechimlardan foydalanganlar:
- O'z-o'ziga havola qilish (
that = this
): Qayta chaqiruvdan oldin 'this' havolasini o'zgaruvchiga saqlash keng tarqalgan usul edi.
function Timer() {
this.seconds = 0;
const that = this; // 'this' kontekstini saqlash
setInterval(function() {
that.seconds += 1;
console.log(that.seconds);
}, 1000);
}
const timer = new Timer();
bind()
: Qayta chaqiruv uchun 'this' kontekstini aniq belgilash uchunbind()
dan foydalanish.
function Timer() {
this.seconds = 0;
setInterval(function() {
this.seconds += 1;
console.log(this.seconds);
}.bind(this), 1000);
}
const timer = new Timer();
Ushbu usullar 'this' har doim kutilgan ob'ektga ishora qilishini ta'minlab, muammoni samarali hal qildi. Biroq, ular ko'proq yozishni talab qiladi va yodda tutish hamda qo'llash uchun ongli sa'y-harakatni talab qiladi.
Strela Funksiyalarini Ta'qdim Etish: Oddiyroq Yondashuv
ECMAScript 6 (ES6) strela funksiyalarini taqdim etdi, ular yanada ixcham sintaksisni va muhimi, 'this' bog'lanishiga boshqacha yondashuvni taqdim etadi. Strela funksiyalarining asosiy xususiyati shundaki, ularning o'z 'this' bog'lanishi yo'q. Buning o'rniga, ular o'zlarining tashqi doirasidan 'this' qiymatini leksik jihatdan tutib oladilar.
Leksik 'this' degan ma'noni anglatadi, strela funksiyasi ichidagi 'this' tashqi strela funksiyasidagi 'this' bilan bir xil, qayerda bo'lsa ham.
Keling, strela funksiyasidan foydalanib Timer
misolini ko'rib chiqaylik:
function Timer() {
this.seconds = 0;
setInterval(() => {
// Strela funksiyasi ichidagi 'this' leksik jihatdan bog'langan
// Timer funksiyasining tashqi doirasidagi 'this' ga.
this.seconds += 1;
console.log(this.seconds);
}, 1000);
}
const timer = new Timer();
Bu ancha toza. Strela funksiyasi () => { ... }
uni aniqlagan Timer
konstruktor funksiyasidan 'this' kontekstini avtomatik ravishda meros qilib oladi. Ushbu maxsus foydalanish holati uchun that = this
yoki bind()
ga hojat yo'q.
'this' Uchun Strela Funksiyalaridan Qachon Foydalanish Kerak
Strela funksiyalari quyidagilar uchun idealdir:
- Siz tashqi doiradan 'this'ni meros qilib oladigan funksiyaga muhtoj bo'lganda.
- Siz
setTimeout
,setInterval
, massiv uslublari (map
,filter
,forEach
) yokithis
kontekstini saqlab qolmoqchi bo'lgan hodisa tinglovchilari kabi uslublar uchun qayta chaqiruvlarni yozayotganingizda.
'this' Uchun Strela Funksiyalaridan Qachon Foydalanmaslik Kerak
Strela funksiyalari mos kelmaydigan vaziyatlar mavjud va an'anaviy funksiya ifodasi yoki deklaratsiyasidan foydalanish zarur bo'ladi:
- Ob'ekt Metodlari: Agar siz funksiyani ob'ekt metodi bo'lishini istasangiz va 'this' o'sha ob'ektga ishora qilsin desangiz, oddiy funksiyadan foydalaning.
const counter = {
count: 0,
// Metod uchun oddiy funksiyadan foydalanish
increment: function() {
this.count++;
console.log(this.count);
},
// Bu yerda strela funksiyasidan foydalanish 'this' uchun kutilganidek ishlamaydi
// incrementArrow: () => {
// this.count++; // 'this' 'counter' ga ishora qilmaydi
// }
};
counter.increment(); // Natija: 1
Agar incrementArrow
strela funksiyasi sifatida aniqlangan bo'lsa, 'this' leksik jihatdan tashqi doiraga (katta ehtimol bilan global ob'ekt yoki qat'iy rejimda undefined
) bog'langan bo'lardi, counter
ob'ektiga emas.
- Konstruktorlar: Strela funksiyalar konstruktor sifatida ishlatilishi mumkin emas. Ularning o'z 'this' yo'q va shuning uchun
new
kalit so'zi bilan chaqirilishi mumkin emas.
// const MyClass = () => { this.value = 1; }; // Bu 'new' bilan ishlatilganda xatolik beradi
// const instance = new MyClass();
- Hodisa Tinglovchilari qayerda 'this' DOM elementi bo'lishi kerak: Hodisa tinglovchisi misolida ko'rsatilganidek, agar siz 'this' hodisani keltirib chiqargan DOM elementiga ishora qilishini istasangiz, siz an'anaviy funksiya ifodasidan foydalanishingiz kerak.
// Bu kutilganidek ishlaydi:
button.addEventListener('click', function() {
console.log(this); // 'this' tugma hisoblanadi
});
// Bu kutilganidek ishlamaydi:
// button.addEventListener('click', () => {
// console.log(this); // 'this' leksik jihatdan bog'langan bo'lardi, tugma emas
// });
'this' Bog'lanishi uchun Global E'tiborlar
Global jamoa bilan dasturiy ta'minotni ishlab chiqish turli xil kodlash uslublari, loyiha sozlamalari va meros qolgan kod bazalarini duch kelishni anglatadi. 'this' bog'lanishini to'g'ri tushunish uzluksiz hamkorlik uchun zarurdir.
- Qat'iylik Muhim: Strela funksiyalari va an'anaviy funksiyalarni qachon ishlatish bo'yicha aniq jamoa konvensiyalarini o'rnating, ayniqsa 'this' bog'lanishiga nisbatan. Ushbu qarorlarni hujjatlashtirish muhimdir.
- Muhitni Bilish: Kodingiz qat'iy yoki qat'iy bo'lmagan rejimda ishlayotganini yodda tuting. Qat'iy rejimning bare funksiya qo'ng'iroqlari uchun
undefined
zamonaviy standart va xavfsizroq amaliyotdir. - 'this' Xulqini Sinash: 'this' bog'lanishi muhim bo'lgan funksiyalarni to'liq sinab ko'ring. Turli chaqiruv stsenariylarida 'this' kutilgan kontekstga ishora qilishini tasdiqlash uchun birlik sinovlaridan foydalaning.
- Kod Ko'rib Chiqish: Kod ko'rib chiqish paytida 'this' qanday boshqarilayotganiga diqqat qiling. Bu nozik xatolar kiritilishi mumkin bo'lgan keng tarqalgan sohadir. Ko'rib chiquvchilarni 'this' foydalanishini, ayniqsa qayta chaqiruvlar va murakkab ob'ekt tuzilmalarida so'rashga undash.
- Zamonaviy Xususiyatlardan Foydalanish: Zarur bo'lganda strela funksiyalaridan foydalanishni rag'batlantiring. Ular ko'pincha keng tarqalgan muvaffaqiyatsiz naqshlar uchun 'this' kontekstini boshqarishni soddalashtirib, yanada o'qiladigan va parvarishlanadigan kodga olib keladi.
Xulosa: Kontekst O'zgarishi vs. Leksik Bog'lanish
'this' bog'lanishi bo'yicha an'anaviy funksiyalar va strela funksiyalari o'rtasidagi asosiy farq quyidagicha umumlashtirilishi mumkin:
- An'anaviy Funksiyalar: 'this' qanday chaqirilishiga qarab dinamik ravishda bog'lanadi (metod, konstruktor, global va hokazo). Bu kontekst o'zgarishi.
- Strela Funksiyalari: 'this' strela funksiyasi aniqlangan tashqi doiraga leksik jihatdan bog'lanadi. Ularning o'z 'this' yo'q. Bu bashoratlilik leksik 'this' xulqini ta'minlaydi.
'this' bog'lanishini o'zlashtirish har qanday JavaScript dasturchisi uchun o'tish marosimidir. An'anaviy funksiyalar uchun qoidalarni tushunish va strela funksiyalarining qat'iy leksik bog'lanishidan foydalanish orqali siz yanada toza, ishonchliroq va parvarishlanadigan JavaScript kodini yozishingiz mumkin, geografik joylashuvingiz yoki jamoaviy tuzilmangizdan qat'iy nazar.
Dunyo Bo'ylab Dasturchilar uchun Amalga Oshiriladigan Ma'lumotlar
Mana ba'zi amaliy xulosalar:
- Qayta Chaqiruvlar Uchun Strela Funksiyalariga Afzallik Bering: Muvaffaqiyatsiz operatsiyalarga (
setTimeout
,setInterval
, Promises, element target 'this' bo'lmagan hodisa tinglovchilari) funksiyalarni uzatganda, ularning bashoratlilik 'this' bog'lanishi uchun strela funksiyalarini afzal ko'ring. - Ob'ekt Metodlari Uchun Oddiy Funksiyalardan Foydalaning: Agar funksiya ob'ekt metodi bo'lishi va 'this' orqali o'sha ob'ektning xususiyatlariga kirish zarur bo'lsa, oddiy funksiya deklaratsiyasi yoki ifodasidan foydalaning.
- Konstruktorlar Uchun Strela Funksiyalaridan Qoching: Ular
new
kalit so'zi bilan mos kelmaydi. - Zarur Bo'lganda
bind()
bilan Aniq Bo'ling: Strela funksiyalari ko'p muammolarni hal qilsa-da, ba'zan sizga hali hambind()
kerak bo'lishi mumkin, ayniqsa eski kod yoki funksiyani mustaqil ravishda uzatiladigan holatlar uchun 'this'ni oldindan o'rnatish kerak bo'lgan murakkabroq funktsional dasturlash naqshlari bilan ishlayotganda. - Jamoangizni O'qiting: Bu bilimni ulashing. Barcha jamoa a'zolari ushbu tushunchalarni tushunishlarini ta'minlang, umumiy xatolardan qoching va butun bo'ylab kod sifatini saqlang.
- Linters va Statik Tahlildan Foydalaning: ESLint kabi vositalar umumiy 'this' bog'lanish xatolarini tutish uchun sozlanishi mumkin, bu jamoa konvensiyalarini kuchaytirishga va xatoliklarni erta aniqlashga yordam beradi.
Ushbu printsiplarni o'zlashtirish orqali, har qanday kelib chiqishdan bo'lgan dasturchilar JavaScriptning 'this' kalit so'zining murakkabliklarini ishonch bilan boshqarishlari mumkin, bu esa yanada samaraliroq va hamkorlikdagi dasturlash tajribalariga olib keladi.