Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. this — chaqiruv paytida aniqlanadi
- 2.1 Bitta funksiya — ikki xil this
- 2.2 Bitta savol: "qanday chaqirildi?"
- 3. 1-qoida: metod sifatida chaqiruv
- 3.1 Nuqtadan oldingi obyekt
- 3.2 Kvadrat qavs va ichma-ich obyekt
- 4. 2-qoida: oddiy chaqiruv
- 4.1 Strict rejimda — undefined
- 4.2 Oddiy skriptda — global obyekt
- 4.3 Eng yuqori darajadagi this
- 5. 3-qoida: call bilan aniq berish
- 6. 4-qoida: new bilan chaqirish
- 7. Qoidalar to'qnashsa: ustuvorlik
- 8. Arrow funksiya istisnosi
- 8.1 Arrow'da o'z this yo'q
- 8.2 Metod ichidagi callback — arrow'ning eng yaxshi joyi
- 8.3 Arrow'ni qayta bog'lab bo'lmaydi
- 9. Brauzerda: hodisa tinglovchisidagi this
- 10. Ko'p uchraydigan xatolar
- 10.1 Metod arrow bilan yozilgan
- 10.2 Ichki function tashqi this ni kutadi
- 10.3 this. ni unutish
- 10.4 this — funksiyaning o'zi deb o'ylash
- 11. Mashqlar
- 1-mashq (oson): this kim?
- 2-mashq (o'rta): Kassani tuzating
- 3-mashq (qiyin): Ikki muhit
- 4-mashq: Vazifalar qadami — this auditi
- 12. Real ishda
- Xulosa
- Manbalar
JavaScript this: to'rt qoida va arrow funksiya istisnosi
Qisqacha:
this— funksiya ichidagi maxsus so'z. Uning qiymati funksiya qayerda yozilganiga emas, qanday chaqirilganiga bog'liq. To'rt qoida bor:obyekt.metod()—thiso'sha obyekt; oddiyf()— strict rejimdaundefined;f.call(x)—this=x;new F()—this= yangi obyekt. Arrow funksiya istisno: uning o'zthisi yo'q, uthisni o'zi yozilgan joydan oladi.
Bu darsda
- Har qanday chaqiruvga qarab
thisnimaga teng bo'lishini to'rt qoida bilan aniqlay olasiz. - Qoidalar to'qnashganda qaysi biri ustun kelishini bilasiz.
- Arrow funksiya nega
thisni "tashqaridan" olishini va buni qayerda foydali ishlatishni tushuntira olasiz. - Node (
.mjsva.cjs) va brauzerdagi (<script>vatype="module") farqlarni bilasiz. vazifalardagi tinglovchilarni tekshirib, "thiso'rnigaevent" qarorini hujjatlashtirasiz.
Oldin bilishingiz kerak: Shorthand, computed kalitlar va metodlar, Function expression va arrow funksiyalar, Global obyekt va globalThis, Strict mode, addEventListener asoslari.
1. Nega bu kerak?
this bilan ikki marta uchrashgansiz. Metodlar darsida hamyon.korsat() ichidagi this — hamyon edi. addEventListener asoslari darsida esa oddiy function tinglovchidagi this — tugma edi, arrow funksiyadagisi — window.
O'shanda ikkala safar ham "to'liq qoidalar keyinroq" degan edik. Sababi bor: this JavaScript'dagi eng ko'p chalkashtiradigan so'zlardan biri. Bir xil this.ism bitta joyda "Ali", boshqa joyda undefined, uchinchi joyda esa TypeError beradi. Kod o'zgarmagan — faqat funksiya boshqacha chaqirilgan.
Hayotdan o'xshatish: "men" so'zi. Otabek "men ofitsiantman" desa, "men" — Otabek. Rustam aka xuddi shu gapni aytsa, "men" — Rustam aka. Gap bir xil, ma'nosi esa kim aytayotganiga bog'liq. this ham shunday: funksiya bitta, this esa uni kim va qanday chaqirganiga qarab o'zgaradi.
Bugun shu "kim chaqirdi?" savoliga javob beradigan to'rtta qoidani o'rganamiz. Keyin ularning yagona istisnosi — arrow funksiyani ko'ramiz. Oxirida Node va brauzer qanday farq qilishini aniq ko'rib chiqamiz.
2. this — chaqiruv paytida aniqlanadi
2.1 Bitta funksiya — ikki xil this
«Bahor» xodimlari o'zini tanishtiradi. Funksiyani bir marta yozamiz va ikkita obyektga metod qilib beramiz:
function tanishtir() {
console.log(`${this.ism} — ${this.lavozim}`);
}
const otabek = { ism: "Otabek", lavozim: "ofitsiant", tanishtir };
const rustam = { ism: "Rustam aka", lavozim: "oshpaz", tanishtir };
otabek.tanishtir();
rustam.tanishtir();Konsolda:
Otabek — ofitsiant
Rustam aka — oshpaztanishtir funksiyasi xotirada bitta. otabek.tanishtir va rustam.tanishtir — o'sha bitta funksiyaga ikkita havola (Havola semantikasi). Lekin natija ikki xil chiqdi. Demak this funksiya yozilganda emas, har chaqiruvda qaytadan aniqlanadi.
Qadamma-qadam yuring. Har chaqiruvda this ga nima tushishini kuzating:
2.2 Bitta savol: "qanday chaqirildi?"
this ni aniqlash uchun funksiyaning ichiga qaramang. Uni chaqirgan qatorni toping va to'rt savol bering:
newbilan chaqirildimi?call(yoki uning qarindoshlari) bilan chaqirildimi?obyekt.metod()shaklida — nuqta bilan chaqirildimi?- Hech biri emas — oddiy
f()mi?
Har savolning o'z qoidasi bor. Ularni eng ko'p uchraydiganidan boshlab ko'ramiz, ustuvorlik tartibini esa oxirida yig'amiz.
3. 1-qoida: metod sifatida chaqiruv
3.1 Nuqtadan oldingi obyekt
Bu qoidani 08-qismdan bilasiz: obyekt.metod() chaqirilsa, this — nuqtadan oldingi obyekt. Inglizcha nomi — implicit binding ("yashirin bog'lanish"): this ni hech kim aniq aytmadi, uni chaqiruv shaklining o'zi bildirdi.
Muhim so'z — chaqirilsa. Funksiya qaysi obyekt ichida yozilgani emas, chaqiruv qatorida nuqtadan oldin nima turgani hal qiladi. «Bitta funksiya — ikki xil this» bo'limida tanishtir hech qaysi obyekt ichida yozilmagan edi, lekin baribir ikkalasida to'g'ri ishladi.
3.2 Kvadrat qavs va ichma-ich obyekt
Nuqta o'rniga kvadrat qavs ham xuddi shunday ishlaydi. Ichma-ich obyektda esa oxirgi nuqtadan oldingi obyekt olinadi:
const bahor = {
nom: "Bahor",
oshxona: {
oshpaz: "Rustam aka",
kim() {
return this.oshpaz;
},
},
};
console.log(bahor.oshxona.kim()); // Rustam aka
console.log(bahor["oshxona"]["kim"]()); // Rustam akabahor.oshxona.kim() da ikkita nuqta bor. kim dan oldingi obyekt — bahor.oshxona. Shuning uchun this — oshxona, bahor emas. this.nom yozsangiz undefined chiqardi: oshxona da nom yo'q.
Tekshirib ko'ring:
const a = { x: 1, b: { x: 2, f() { return this.x; } } };bo'lsa,a.b.f()nima qaytaradi?
Javob
2. f dan oldingi obyekt — a.b, demak this.x — a.b.x. Tashqi a dagi x: 1 ga this umuman qaramaydi.
4. 2-qoida: oddiy chaqiruv
4.1 Strict rejimda — undefined
Endi o'sha tanishtir ni nuqtasiz, oddiy funksiya kabi chaqiramiz:
"use strict";
function tanishtir() {
console.log(`${this.ism} — ${this.lavozim}`);
}
tanishtir();TypeError: Cannot read properties of undefined (reading 'ism')Tarjimasi: "undefined ning xususiyatlarini o'qib bo'lmaydi (ism ni o'qishda)". Nuqtadan oldin hech narsa yo'q — hech kim "men chaqirdim" demadi. Bu default binding ("sukut bo'yicha bog'lanish"): strict rejimda bunday chaqiruvda this — undefined. undefined.ism ni o'qishga urinish esa TypeError beradi.
Birinchi qatordagi "use strict"; ga e'tibor bering. this ni sinayotganda kod qayerda ishlashi muhim. Node'dagi .mjs fayl — modul, modul esa doim strict. Saytdagi «Ishga tushir» tugmasi ham kodni brauzerda strict rejimda bajaradi. Bu va keyingi darslarning ba'zi misollari baribir "use strict"; bilan boshlanadi: kodni .cjs faylga yoki oddiy <script> ga ko'chirsangiz ham, natija o'zgarmasin (Strict mode). Bitta farq qoladi — eng yuqori darajadagi this: Node modulida u undefined, brauzer skriptida esa (strict bo'lsa ham) window. Buni «Eng yuqori darajadagi this» bo'limida ko'ramiz.
4.2 Oddiy skriptda — global obyekt
Strict bo'lmagan ("sloppy", ya'ni "bo'sh") rejimda qoida boshqacha: this o'rniga global obyekt qo'yiladi. Xuddi shu kodni oddiy skript sifatida — .cjs faylda — ishga tushiramiz:
function kim() {
return this;
}
console.log(kim() === globalThis); // trueEndi this — globalThis. Xato chiqmaydi, lekin bu yaxshilik emas. this.ism jimgina undefined beradi, this.ism = "Ali" esa global obyektga yangi xususiyat yozib qo'yadi:
function ismQoy(ism) {
this.ism = ism;
}
ismQoy("Ali");
console.log(globalThis.ism); // AliismQoy hech qaysi obyektga tegishli emas. U "o'z" obyektiga ism yozmoqchi edi, lekin this global obyekt bo'lib chiqdi. Endi butun dasturda ism degan global nom paydo bo'ldi. U boshqa kodning shu nomli o'zgaruvchisi bilan to'qnashishi mumkin (Global obyekt va globalThis). Strict rejim aynan shu jim xatoni baland ovozli TypeError ga aylantiradi — Strict mode darsidagi asosiy g'oya.
4.3 Eng yuqori darajadagi this
Funksiyadan tashqarida — faylning eng yuqori darajasida — ham this bor. U muhitga bog'liq. Bitta qatorni ikki faylda — bosh.mjs va bosh.cjs da — node bilan ishga tushiring:
console.log(this);.mjs modulda — undefined. .cjs faylda esa — {}, bo'sh obyekt. Biz ikkalasini Node 24 da tekshirdik. Bu qatorni saytdagi tugma bilan emas, fayl bilan sinang: brauzer skriptida u Window obyektini chiqaradi.
Bu {} — Node'ning CommonJS tizimi har faylga beradigan module.exports obyekti. CommonJS'ni CommonJS va ESM darsida o'rganamiz — hozir bilish shart emas.
To'rt muhitni yonma-yon yig'amiz. Ikkinchi ustun — eng yuqori darajadagi this, uchinchisi — oddiy f() ichidagi this:
| Muhit | Yuqori daraja | Oddiy f() ichida |
|---|---|---|
Node, .mjs (modul) |
undefined |
undefined |
Node, .cjs |
{} |
globalThis |
Brauzer, <script> |
window |
window |
Brauzer, type="module" |
undefined |
undefined |
Funksiya ichida qoida bitta: modulda va strict rejimda — undefined, eski uslubdagi skriptda — global obyekt. Yuqori darajada esa: modulda — undefined, skriptda — global obyekt (Node .cjs da — {}). Zamonaviy kod deyarli doim modul, shuning uchun asosan birinchi va to'rtinchi qatorlarni uchratasiz.
Tekshirib ko'ring:
.mjsfayldafunction f() { return this; }vaconsole.log(f());yozildi. Nima chiqadi?.cjsda-chi?
Javob
.mjs da — undefined: modul strict, oddiy chaqiruvda this yo'q. .cjs da — global obyekt (globalThis), chunki u strict emas. .cjs dagi {} — faqat yuqori darajadagi this; funksiya ichida esa qoida boshqa.
5. 3-qoida: call bilan aniq berish
Ba'zan this ni o'zimiz tanlagimiz keladi. Har funksiyada call degan metod bor: f.call(obyekt) funksiyani darhol chaqiradi va this ga obyekt ni qo'yadi. Bu explicit binding ("aniq bog'lanish"):
function tanishtir() {
return `${this.ism}: ${this.lavozim}`;
}
const jasur = { ism: "Jasur aka", lavozim: "egasi" };
console.log(tanishtir.call(jasur)); // Jasur aka: egasijasur da tanishtir metodi yo'q. Lekin call funksiyani "go'yo jasur ning metodidek" chaqirdi. call ning to'liq imkoniyatlari, uning ikki qarindoshi — apply va bind — call, apply, bind darsida. Hozircha bitta narsani eslab qoling: call ga birinchi bo'lib berilgan narsa — this.
6. 4-qoida: new bilan chaqirish
To'rtinchi qoida funksiyani new kalit so'zi bilan chaqirganda ishlaydi:
function Buyurtma(taom) {
this.taom = taom;
this.holati = "kutilmoqda";
}
const birinchi = new Buyurtma("Osh");
console.log(birinchi);Konsolda:
Buyurtma { taom: 'Osh', holati: 'kutilmoqda' }Node obyekt oldiga funksiya nomini — Buyurtma ni — yozib qo'ydi: "bu obyektni Buyurtma yasagan".
new avval yangi bo'sh obyekt yaratadi, keyin funksiyani shu obyektni this qilib chaqiradi. Funksiya return yozmasa ham, new o'sha yangi obyektni qaytaradi. Shunday new bilan chaqirish uchun yozilgan funksiya konstruktor (constructor) deyiladi — xuddi qolipdan bir xil g'isht quyadigan usta kabi. Nom katta harf bilan boshlangani — "bu new bilan chaqiriladi" degan kelishuv. Bu mexanizmning to'rt qadami Konstruktor funksiya va new darsida — hozir faqat qoidani eslab qoling: new F() da this — yangi obyekt.
7. Qoidalar to'qnashsa: ustuvorlik
Bitta chaqiruvda ikki qoida bir vaqtda "ishlashi" mumkin. Masalan, nuqta ham bor, call ham:
function tanishtir() {
return this.ism;
}
const otabek = { ism: "Otabek", tanishtir };
const jasur = { ism: "Jasur aka" };
console.log(otabek.tanishtir.call(jasur)); // Jasur akaNuqtadan oldin otabek turibdi, lekin call ga jasur berilgan. Natija — Jasur aka: aniq aytilgan this yashirinidan kuchli.
To'liq tartib — kuchlidan kuchsizga:
| O'rin | Qoida | Chaqiruv | this |
|---|---|---|---|
| 1 | new |
new F() |
yangi obyekt |
| 2 | Aniq | f.call(x) |
x |
| 3 | Metod | obj.f() |
obj |
| 4 | Oddiy | f() |
undefined yoki global |
new hatto aniq bog'lashdan ham kuchli — buni bind bilan keyingi darslarda ko'ramiz. Bu ro'yxatning tepasida yana bitta tekshiruv turadi: funksiya arrow'mi? Arrow bo'lsa, to'rt qoidaning hech biri ishlamaydi. Sxemani yuqoridan pastga o'qing — bu this ni aniqlashning to'liq algoritmi:
flowchart TD
A{"Arrow funksiyami?"} -- "ha" --> L["Yozilgan joydagi this"]
A -- "yo'q" --> N{"new F() ?"}
N -- "ha" --> Y["Yangi obyekt"]
N -- "yo'q" --> C{"f.call(x) ?"}
C -- "ha" --> X["x"]
C -- "yo'q" --> M{"obj.f() ?"}
M -- "ha" --> O["obj"]
M -- "yo'q" --> D["Strict: undefined<br/>Skript: global"]Tekshirib ko'ring:
rustam.tanishtir.call(otabek)—thiskim?
Javob
otabek. Nuqtadan oldin rustam, lekin call (aniq bog'lanish) metod qoidasidan ustun. Sxemada call savoli obj.f() savolidan oldin keladi.
8. Arrow funksiya istisnosi
8.1 Arrow'da o'z this yo'q
Arrow funksiyalar darsida "arrow'da this boshqacha ishlaydi" degan edik. Endi aniq aytamiz: arrow funksiyaning o'z this i yo'q. Uning ichida this yozsangiz, JavaScript uni oddiy o'zgaruvchidek tashqi scope dan qidiradi — arrow yozilgan joydagi this ni oladi. Buni leksik this deyishadi ("leksik" — "kod matnida qayerda turganiga qarab").
Shuning uchun metodni arrow bilan yozish ishlamaydi:
const otabek = {
ism: "Otabek",
tanishtir: () => this?.ism,
};
console.log(otabek.tanishtir()); // undefinedArrow obyekt ichida yozilgandek ko'rinadi. Lekin obyekt literali o'zining this ini yaratmaydi — { } qavslari funksiya emas. Arrow yozilgan joy — faylning eng yuqori darajasi. U yerda this modulda undefined, brauzer skriptida window — ikkalasida ham ism yo'q. Metodlar darsidagi "metodni arrow bilan yozmang" qoidasining sababi shu.
8.2 Metod ichidagi callback — arrow'ning eng yaxshi joyi
Arrow'ning bu xususiyati kamchilik emas — ko'pincha aynan kerakli narsa. «Bahor» menyusini chiqaradigan metodni ko'ring:
const menyu = {
nom: "Bahor",
taomlar: ["osh", "manti"],
chiqar() {
this.taomlar.forEach((taom) => {
console.log(`${this.nom}: ${taom}`);
});
},
};
menyu.chiqar();Konsolda:
Bahor: osh
Bahor: mantichiqar — oddiy metod, menyu.chiqar() chaqirildi, demak uning this i — menyu. Ichidagi arrow callback'ning o'z this i yo'q, u chiqar niki bilan bir xil. Shuning uchun this.nom — "Bahor".
Endi callback'ni oddiy function ga almashtiring:
"use strict";
const menyu = {
nom: "Bahor",
taomlar: ["osh"],
chiqar() {
this.taomlar.forEach(function () {
console.log(this);
});
},
};
menyu.chiqar(); // undefinedforEach callback'ni oddiy chaqiradi — callback(element, index, array), nuqtasiz. Oddiy function ning o'z this i bor va u 2-qoida bo'yicha undefined bo'ldi. Ichki funksiya tashqi metodning this ini "meros" olmaydi.
Arrow paydo bo'lishidan (2015) oldin dasturchilar bu muammoni const self = this; bilan aylanib o'tishgan: tashqi this ni oddiy o'zgaruvchiga saqlab, callback ichida self.nom deb yozishgan. Eski kodda self yoki that ni ko'rsangiz — sababi shu. Bu self — oddiy o'zgaruvchi nomi; Global obyekt darsidagi brauzerning global self i bilan aloqasi yo'q, uni shunchaki to'sib qo'yadi.
8.3 Arrow'ni qayta bog'lab bo'lmaydi
Arrow'ning this i yozilgan paytda "qotadi". Uni hech narsa o'zgartira olmaydi — call ham, new ham:
const kimArrow = () => this?.ism;
console.log(kimArrow.call({ ism: "Ali" })); // undefinedcall berilgan obyektni jimgina e'tiborsiz qoldirdi. new esa umuman ishlamaydi:
const Buyurtma = (taom) => {
this.taom = taom;
};
new Buyurtma("Osh");TypeError: Buyurtma is not a constructorTarjimasi: "Buyurtma — konstruktor emas". Arrow'ning this i yo'q — new yangi obyektni qo'yadigan joy topa olmaydi. Shuning uchun arrow'ni new bilan chaqirib bo'lmaydi.
Callback imzosi darsida va'da qilingan thisArg ham shu yerda tushunarli bo'ladi. forEach(callback, thisArg) ning ikkinchi argumenti oddiy function callback uchun this bo'ladi, arrow'ga esa ta'sir qilmaydi:
const bahor = { nom: "Bahor" };
[1].forEach(function () {
console.log(this.nom);
}, bahor);
[1].forEach(() => {
console.log(this?.nom);
}, bahor);Konsolda:
Bahor
undefinedZamonaviy kodda thisArg deyarli ishlatilmaydi: arrow callback tashqi this ni o'zi ko'radi.
Tekshirib ko'ring: Nega «Metod ichidagi callback» bo'limidagi birinchi
chiqarishladi, ikkinchisi esa yo'q? Bitta gap bilan.
Javob
Arrow callback'ning o'z this i yo'q va u chiqar ning this ini (menyu) oladi; oddiy function callback'ning esa o'z this i bor va forEach uni nuqtasiz chaqirgani uchun u undefined bo'ladi.
9. Brauzerda: hodisa tinglovchisidagi this
addEventListener asoslari darsida oddiy function tinglovchida this — element ekanini ko'rgan edik. Endi buning qaysi qoida ekanini aytamiz: brauzer tinglovchini o'zi chaqiradi va this ga tinglovchi turgan elementni aniq qo'yadi. Ya'ni bu — 3-qoida, aniq bog'lanish. Bu element — event.currentTarget (Event obyekti).
Quyidagi natijada ikki skript bor: oddiy <script> va type="module". Har birida bittadan tugma, har tugmada ikkitadan tinglovchi — oddiy function va arrow:
<style>
body { font: 1rem/1.5 system-ui, sans-serif; margin: 1rem; }
button { font: inherit; padding: 0.4rem 1rem; margin: 0.25rem; }
</style>
<button id="osh" type="button">Osh (skript)</button>
<button id="manti" type="button">Manti (modul)</button>
<script>
console.log("skript:", this === window);
const osh = document.getElementById("osh");
osh.addEventListener("click", function (event) {
console.log("function:", this === event.currentTarget);
});
osh.addEventListener("click", () => {
console.log("arrow:", this === window);
});
</script>
<script type="module">
console.log("modul:", this);
const manti = document.getElementById("manti");
manti.addEventListener("click", function () {
console.log("function:", this.id);
});
manti.addEventListener("click", () => {
console.log("arrow:", this);
});
</script>Sahifa ochilishi bilan konsolda:
skript: true
modul: undefinedEndi tugmalarni bosing. «Osh (skript)» konsolga function: true va arrow: true yozadi. «Manti (modul)» esa function: manti va arrow: undefined yozadi. Biz buni Chrome'da tekshirdik.
Nimaga qarash kerak:
- Oddiy
function— ikkala skriptda ham element. Modul strict, lekin bu yerdathisni brauzer aniq bergan. Strict rejim faqat "hech kim bermagan" holatda (2-qoida)undefinedqo'yadi. - Arrow — yozilgan joydagi
this. Oddiy skriptning eng yuqori darajasida uwindow, modulda —undefined. Arrow tinglovchidathis.classListyozsangiz, birinchisidawindow.classList(undefined), ikkinchisidaundefined.classList— ikkalasida hamTypeError. - Delegation'da
this— tinglovchi turgan ota element, bosilgan tugma emas (Event delegation).
Shuning uchun zamonaviy kodda tinglovchida this deyarli yozilmaydi. Element kerak bo'lsa — event.currentTarget, bosilgan narsa kerak bo'lsa — event.target. Ular arrow'da ham, function da ham bir xil ishlaydi va kodni o'qigan odam "bu yerda this nima ekan?" deb o'ylamaydi.
10. Ko'p uchraydigan xatolar
10.1 Metod arrow bilan yozilgan
«Arrow'da o'z this yo'q» bo'limidagi tanishtir: () => this — eng ko'p uchraydigan xato. Modulda this.ism o'qilsa — TypeError: Cannot read properties of undefined (reading 'ism'). Oddiy skriptda xato chiqmaydi, faqat undefined — bu yanada xavfli. Tuzatish: metod shorthand — tanishtir() { ... }.
10.2 Ichki function tashqi this ni kutadi
Metod ichida forEach(function () { this... }) yoki setTimeout(function () { this... }) — ichki funksiyaning this i boshqa. Tuzatish: ichki callback'ni arrow qiling.
10.3 this. ni unutish
const hamyon = {
balans: 50000,
toldir(summa) {
balans += summa;
},
};
hamyon.toldir(1000);ReferenceError: balans is not definedTarjimasi: "balans aniqlanmagan". Metod ichida xususiyat nomi o'z-o'zidan o'zgaruvchiga aylanmaydi. JavaScript balans ni scope zanjiri bo'ylab qidirdi va topmadi. Tuzatish: this.balans += summa;.
10.4 this — funksiyaning o'zi deb o'ylash
this funksiyani ham, uning scope'ini ham bildirmaydi. U faqat chaqiruv shakliga qarab tanlangan obyekt (yoki undefined). Funksiyaning o'z o'zgaruvchilari — scope'da, this da emas.
11. Mashqlar
1-mashq (oson): this kim?
Kodni ishga tushirmasdan, har console.log nima chiqarishini yozing. Keyin tekshiring.
"use strict";
function nom() {
return this?.nom;
}
const stol = { nom: "5-stol", nom };
const zal = { nom: "Katta zal", stol };
console.log(stol.nom());
console.log(zal.stol.nom());
console.log(nom());
console.log(nom.call(zal));Ishora: ?. — optional chaining: this undefined bo'lsa, xato o'rniga undefined qaytadi. { nom: "5-stol", nom } da kalit ikki marta yozilgan — ikkinchisi birinchisining ustidan yozadi.
Yechim
Shoshilmang — bu mashqda tuzoq bor. { nom: "5-stol", nom } da ikkinchi nom (funksiya) birinchisining (satrning) ustidan yozildi. Demak stol.nom — funksiya, this.nom ham o'sha funksiya:
"use strict";
function nom() {
return this?.nom;
}
const stol = { nom: "5-stol", nom };
const zal = { nom: "Katta zal", stol };
console.log(stol.nom());
console.log(zal.stol.nom());
console.log(nom());
console.log(nom.call(zal));Konsolda:
[Function: nom]
[Function: nom]
undefined
Katta zalBirinchi ikkitasida this — stol (ikkinchisida ham oxirgi nuqtadan oldin stol), stol.nom esa funksiya. Uchinchisi — oddiy chaqiruv, this — undefined, ?. xatoni to'xtatdi. To'rtinchisida call this ga zal ni qo'ydi. Saboq: xususiyat va metodga bir xil nom bermang.
2-mashq (o'rta): Kassani tuzating
Kassa metodlari ishlamayapti. Ikki xatoni toping va tuzating — natija Jami: 63000 so'm bo'lsin.
const kassa = {
cheklar: [35000, 28000],
jami: 0,
hisobla: () => {
this.cheklar.forEach(function (summa) {
this.jami += summa;
});
},
};
kassa.hisobla();
console.log(`Jami: ${kassa.jami} so'm`);Yechim
const kassa = {
cheklar: [35000, 28000],
jami: 0,
hisobla() {
this.cheklar.forEach((summa) => {
this.jami += summa;
});
},
};
kassa.hisobla();
console.log(`Jami: ${kassa.jami} so'm`); // Jami: 63000 so'mBirinchi xato — metod arrow edi: uning this i modulda undefined. Metod shorthand bilan kassa.hisobla() da this — kassa. Ikkinchi xato — ichki callback oddiy function edi: forEach uni nuqtasiz chaqiradi va this — undefined. Arrow callback esa hisobla ning this ini oladi. Qoida: tashqi — metod, ichki — arrow.
3-mashq (qiyin): Ikki muhit
Quyidagi kod .mjs da va .cjs da ishga tushirilsa, har qator nima chiqaradi? Jadval tuzing, keyin ikkala faylni node bilan ishga tushirib tekshiring (saytdagi tugma bu yerda yordam bermaydi — u brauzer skripti).
function f() {
return this === globalThis;
}
const g = () => this;
console.log(f());
console.log(g());
console.log(typeof this);Yechim
.mjs da:
function f() {
return this === globalThis;
}
const g = () => this;
console.log(f());
console.log(g());
console.log(typeof this);Konsolda:
false
undefined
undefined.cjs da:
function f() {
return this === globalThis;
}
const g = () => this;
console.log(f());
console.log(g());
console.log(typeof this);Konsolda:
true
{}
object| Qator | .mjs |
.cjs |
|---|---|---|
f() |
false — strict, this = undefined |
true — sloppy, global |
g() |
undefined |
{} — module.exports |
typeof this |
"undefined" |
"object" |
g — arrow, shuning uchun u faylning yuqori darajasidagi this ni qaytaradi. .cjs da u {} (module.exports), global obyekt emas! Oddiy f ichida esa .cjs da global obyekt. Bitta faylda uch xil this — shuning uchun zamonaviy kod modullarda yoziladi.
4-mashq: Vazifalar qadami — this auditi
Bu va keyingi ikki darsda vazifalar ning xulqini o'zgartirmaymiz. Avval tekshiruv: vazifalar.js da this bormi va bo'lishi kerakmi?
1. Branch. git switch -c refactor/this-va-bind — u keyingi ikki darsda ham davom etadi.
2. Jadval. vazifalar.js da oltita tinglovchi bor. Har biri uchun yozing: funksiya turi, element qayerdan olinadi va ichida this yozilsa, u nima bo'lardi. Ishora: vazifalar.js <script defer> bilan ulangan — u oddiy skript, modul emas (Yakuniy loyiha).
3. Tajriba. Saytni Live Server'da oching, DevTools Console'ga quyidagini yozing va «Faol» ni bosing:
filtrlar.addEventListener("click", function (event) {
console.log(this === event.currentTarget);
console.log(`${this.id} / ${event.target.dataset.filtr}`);
});filtrlar — vazifalar.js ning yuqori darajasidagi const. Oddiy skriptdagi bunday o'zgaruvchilar konsoldan ham ko'rinadi. Sahifani yangilasangiz, bu vaqtinchalik tinglovchi yo'qoladi.
4. Qaror. Natijaga qarab README.md ga "Kod qoidalari" bo'limini qo'shing: tinglovchilarda this ishlatamizmi yoki yo'qmi va nega.
Yechim
Jadval:
| Tinglovchi | Turi | Element qayerdan | this bo'lardi |
|---|---|---|---|
forma — submit |
arrow | maydon, forma |
window |
maydon — input |
arrow | maydon |
window |
royxat — click |
arrow | event.target.closest(...) |
window |
royxat — keydown |
arrow | event.target |
window |
filtrlar — click |
arrow | event.target.closest(...) |
window |
eksportTugma — click |
arrow | eksportMatn |
window |
Hammasi arrow, vazifalar.js esa oddiy skript. Strict mode darsida uning boshiga "use strict"; qo'shgan edik. Lekin u faqat funksiya ichidagi oddiy chaqiruvga ta'sir qiladi — skriptning yuqori darajasidagi this baribir window. Arrow esa aynan shu this ni oladi. Hech bir tinglovchida this yo'q — va bu to'g'ri.
Tajribada «Faol» bosilganda konsolda:
true
filtrlar / faolOddiy function da this — tinglovchi turgan div#filtrlar, bosilgan tugma emas. Bosilgan tugma — event.target. Delegation'da this bizga kerakli tugmani bermaydi, event.target.closest("[data-filtr]") esa beradi.
README.md ga, oxiriga:
## Kod qoidalari
- Hodisa tinglovchisi — arrow funksiya, parametri `event`.
- Tinglovchi turgan element — `event.currentTarget`,
bosilgan element — `event.target.closest(...)`.
- Tinglovchilarda `this` ishlatilmaydi: arrow'da u `window`,
delegation'da esa ota element bo'ladi.git add README.md
git commit -m "Docs: tinglovchilarda this o'rniga event qoidasini yoz"Kod o'zgarmadi — sayt avvalgidek ishlaydi. Branch'ni hali main ga qo'shmang: keyingi ikki dars shu branch'da davom etadi.
Maslahat: Bu qaror faqat tinglovchilar uchun. Obyekt metodlarida
this— oddiy va to'g'ri vosita. Klasslarni o'rganganda (classsintaksisi) u yana markazga chiqadi.
12. Real ishda
- Intervyu. "
thisnimaga teng?" — JavaScript intervyusidagi eng mashhur savollardan. Odatda kod beriladi va har chaqiruvdathisso'raladi. Javob — shu darsdagi sxema: arrow →new→call→ nuqta → oddiy. - Eski kod. jQuery (2010-yillarning eng mashhur DOM kutubxonasi) va boshqa eski kutubxonalarda tinglovchi ichida
thisjuda ko'p:$(this).hide(). Bunday kodni o'qiyotganda oddiyfunctionekanini tekshiring. - React. Eski React kodida (klass komponentlari)
this.state,this.propsvathis.handleClick.bind(this)uchraydi. Zamonaviy React funksiyalar bilan yoziladi vathisdeyarli yo'q (React — 17-qismda). - Node. Modullarda yuqori darajadagi
this—undefined. Eski CommonJS kodidathis === module.exportsdan foydalanadigan joylarni ham uchratasiz.
Xulosa
thisfunksiya yozilganda emas, chaqirilganda aniqlanadi.- To'rt qoida:
new F()— yangi obyekt;f.call(x)—x;obj.f()—obj; oddiyf()— strict/moduldaundefined, eski skriptda global obyekt. - Ustuvorlik shu tartibda:
new> aniq > metod > oddiy. - Arrow'ning o'z
thisi yo'q: u yozilgan joydagithisni oladi,callvathisArguni o'zgartirmaydi,newbilan chaqirib bo'lmaydi. - Metod — shorthand bilan, metod ichidagi callback — arrow bilan.
- Brauzer tinglovchida
this—event.currentTarget. Zamonaviy kodthiso'rnigaeventdan foydalanadi.
Keyingi dars: this yo'qolishi va uni tiklash — metodni callback sifatida uzatganda this nega yo'qolishini va uni qaytarishning uch usulini ko'ramiz.
Manbalar
- MDN: "this" — developer.mozilla.org
- MDN: "Arrow function expressions" — "Cannot be used as methods" bo'limi
- ECMAScript 2025 Language Specification: "OrdinaryCallBindThis" — tc39.es/ecma262
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!