this parametri — kontekst turi, noImplicitThis

~15 daq · TypeScript · Funksiyalar

Hisoblagich ob'ekti yozilgan. oshirish metodi tugmaga bog'lanadi:

const hisoblagich = {
  qiymat: 0,
  oshirish() {
    this.qiymat++; // bu yerda this = hisoblagich
  }
};

btn.addEventListener("click", hisoblagich.oshirish);
// Tugma bosilganda: this = btn (HTMLButtonElement)
// this.qiymat++ — undefined++, natija NaN

this kontekstga qarab o'zgaradi. JavaScript da bu keng tarqalgan muammo. TypeScript noImplicitThis: true bilan this turini aniq belgilashni talab qiladi.


this parametri

TypeScript funksiyada this turini birinchi parametr sifatida belgilashga imkon beradi. Bu haqiqiy parametr emas — faqat tur tekshirish uchun:

interface Hisoblagich {
  qiymat: number;
  oshirish(this: Hisoblagich): void;
}

const hisoblagich: Hisoblagich = {
  qiymat: 0,
  oshirish() {
    this.qiymat++; // ✅ — this: Hisoblagich, .qiymat mavjud
  }
};

Noto'g'ri kontekstda chaqirish

this parametri yozilganda TypeScript noto'g'ri kontekstda chaqirishni to'xtatadi:

interface Hisoblagich {
  qiymat: number;
  oshirish(this: Hisoblagich): void;
}

function chaqir(fn: () => void) { fn(); }

chaqir(hisoblagich.oshirish);
// ❌ — The 'this' context of type 'void' is not assignable to type 'Hisoblagich'

To'g'ri yechim — bind yoki arrow funksiya:

btn.addEventListener("click", () => hisoblagich.oshirish());
// ✅ — arrow funksiya o'z this ini saqlaydi

btn.addEventListener("click", hisoblagich.oshirish.bind(hisoblagich));
// ✅ — bind bilan kontekst belgilanadi

noImplicitThis

tsconfig.json da "noImplicitThis": true (strict: true bilan avtomatik yoqiladi) bo'lganda — this turi aniqlanmagan funksiyada xato:

function yukla(this, url: string) { // ❌ — this turi noma'lum
  console.log(this.baseUrl + url);
}

this turi belgilanishi kerak:

interface Yuklash {
  baseUrl: string;
}

function yukla(this: Yuklash, url: string): void {
  console.log(this.baseUrl + url); // ✅
}

Arrow funksiya va this

Arrow funksiya o'z this ni yaratmaydi — uni o'rab turgan kontekstdan oladi:

class Taymer {
  hisoblagich = 0;

  boshlash() {
    setInterval(() => {
      this.hisoblagich++; // ✅ — arrow funksiya, this = Taymer instansiyasi
      console.log(this.hisoblagich);
    }, 1000);
  }
}

Oddiy funksiya bilan:

class Taymer {
  hisoblagich = 0;

  boshlash() {
    setInterval(function() {
      this.hisoblagich++; // ❌ — this = undefined (strict mode da)
    }, 1000);
  }
}

Class metodlari ichida callback — arrow funksiya ishlating.


Tez-tez uchraydigan xatolar

Metodni o'zgaruvchiga olib, chaqirish:

const obj = {
  qiymat: 42,
  olish(this: typeof obj) { return this.qiymat; }
};

const fn = obj.olish;
fn(); // ❌ — this konteksti yo'q
obj.olish(); // ✅

Class metodini callback sifatida berish:

class Xizmat {
  ism = "API";
  logla() { console.log(this.ism); }
}

const x = new Xizmat();
setTimeout(x.logla, 1000);       // ❌ — this yo'qoladi
setTimeout(() => x.logla(), 1000); // ✅

Xulosa

// this parametri — haqiqiy parametr emas, faqat tur uchun
function fn(this: Tur, a: string): void { ... }

// Arrow funksiya — this ni o'rab turgan kontekstdan oladi
const fn = () => this.qiymat; // ✅ — this tashqaridan

// bind — kontekstni qat'iy belgilash
const bog_langan = metod.bind(ob_ekt);
Oddiy funksiya    →  this chaqiruvchi ob'ektga qarab o'zgaradi
Arrow funksiya    →  this yaratilgan joydan olinadi (leksik)
.bind(obj)        →  this obj ga qat'iy bog'lanadi

Keyingi dars

27-dars: typeof va instanceof — type narrowing