JavaScript'da 'this' Kontekstini O'zlashtirish

JavaScript'da 'this' Kontekstini O'zlashtirish va 'this'ning Bog'lanish Qoidalari

So'nggi yangilanish: 2024-12-14

JavaScript dunyosida, this kalit so'zi kuchli, ammo ko'pincha noto'g'ri tushunilgan tushunchadir. Bu har bir funksiya doirasida avtomatik ravishda belgilanadigan maxsus identifikator bo'lib, uning qiymati funksiya qanday chaqirilganiga qarab o'zgarishi mumkin. thisni tushunish samarali, qayta ishlatiluvchi va saqlab turiluvchi JavaScript kodini yozish uchun juda muhimdir.

Ushbu keng qamrovli qo'llanma this kalit so'zini tushuntirishga, uning turli kontekstlardagi xatti-harakatlarini o'rganishga, potensial xatolarni ochishga va undan foydalanish bo'yicha eng yaxshi amaliyotlarni taqdim etishga qaratilgan.

'this' nima?

JavaScript'da this kalit so'zi obyektlarga dinamik ravishda bog'lanadigan havoladir. O'zgaruvchilardan farqli o'laroq, thisning qat'iy qiymati yo'q; aksincha, uning qiymati funksiya qanday chaqirilganiga qarab aniqlanadi. Bu dinamik kontekst bog'lanishi thisni ham kuchli, ham ba'zan chalkash qiladi.

Asosiy jihatdan, this funksiyalarga ular chaqirilayotgan obyektga kirish imkonini beruvchi usuldir. U metodlarga obyektning xususiyatlari bilan o'zaro ta'sir qilish va ularni boshqarish imkonini beradi, bu esa JavaScript'da obyektga yo'naltirilgan dasturlash usullarini amalga oshirish imkonini beradi.

'this'ning Bog'lanish Qoidalari

this qanday qiymat olishini tushunish uchun, thisning bog'lanishini aniqlaydigan to'rtta asosiy qoidani bilishimiz kerak:

  1. Standart Bog'lanish: Funksiya global doirada chaqirilganda.
  2. Yashirin Bog'lanish: Funksiya obyektning metodi sifatida chaqirilganda.
  3. Aniq Bog'lanish: call(), apply() yoki bind() metodlari ishlatilganda.
  4. Yangi Bog'lanish: Funksiya new kalit so'zi bilan konstruktor sifatida ishlatilganda.

Keling, bu kontekstlarning har birini batafsil ko'rib chiqaylik.

Global Kontekst

Global bajarish kontekstida (har qanday funksiyadan tashqarida), this global obyektga ishora qiladi. Brauzer muhitida global obyekt windowdir. Node.js'da esa bu globaldir.

Misol:

console.log(this === window); // brauzerda true

var globalVar = "Men global o'zgaruvchiman";
console.log(this.globalVar); // "Men global o'zgaruvchiman"

function createGlobal() {
  this.newGlobalVar = "Men yangi global o'zgaruvchiman";
}
createGlobal();
console.log(window.newGlobalVar); // "Men yangi global o'zgaruvchiman"

Shuni esda tutish muhimki, modullarda (import/export ishlatilganda), yuqori darajadagi this global obyekt emas, balki undefineddir.

Funksiya Konteksti

Funksiya ichidagi thisning qiymati funksiya qanday chaqirilganiga bog'liq. Bu ko'p dasturchilar uchun JavaScript'ning eng chalkash jihatlaridan biridir.

function showThis() {
  console.log(this);
}

// Oddiy funksiya chaqiruvi
showThis(); // qat'iy bo'lmagan rejimda window yoki qat'iy rejimda undefined

// Obyekt metodi sifatida
const obj = { method: showThis };
obj.method(); // obj

// call yordamida this ni o'rnatish
showThis.call({ custom: 'context' }); // { custom: 'context' }

// Konstruktor sifatida
new showThis(); // {} (yangi obyekt)

Bu turli chaqiruv usullarini tushunish JavaScript'da thisni o'zlashtirishning kalitidir.

Obyekt Metodi Konteksti

Funksiya obyektning metodi sifatida chaqirilganda, this metod chaqirilgan obyektga o'rnatiladi. Bu xatti-harakat metodlarga obyektning xususiyatlariga kirish va ularni boshqarish imkonini beradi.

const shaxs = {
  ism: 'Alisher',
  salomlash: function() {
    console.log(`Salom, mening ismim ${this.ism}`);
  },
  do'st: {
    ism: 'Bobur',
    salomlash: function() {
      console.log(`Salom, mening ismim ${this.ism}`);
    }
  }
};

shaxs.salomlash(); // "Salom, mening ismim Alisher"
shaxs.do'st.salomlash(); // "Salom, mening ismim Bobur"

// Ammo ehtiyot bo'ling:
const salomlashFunksiyasi = shaxs.salomlash;
salomlashFunksiyasi(); // "Salom, mening ismim undefined" (qat'iy bo'lmagan rejimda)

Bu oxirgi misol keng tarqalgan xatoni ko'rsatadi: metod o'zgaruvchiga tayinlanganda va keyin chaqirilganda, u o'zining asl this kontekstini yo'qotadi.

Konstruktor Konteksti

Funksiya konstruktor sifatida ishlatilganda (new kalit so'zi bilan chaqirilganda), this yangi yaratilgan obyektga bog'lanadi. Bu bog'lanish funksiya tanasi bajarilishidan oldin sodir bo'ladi.

function Shaxs(ism, yosh) {
  this.ism = ism;
  this.yosh = yosh;
  this.salomlash = function() {
    console.log(`Salom, men ${this.ism}man va ${this.yosh} yoshdaman.`);
  };
}

const alisher = new Shaxs('Alisher', 30);
alisher.salomlash(); // "Salom, men Alisherman va 30 yoshdaman."

// 'new' ni unutsak nima bo'ladi?
const bobur = Shaxs('Bobur', 25); // Xato! 'this' global obyekt yoki qat'iy rejimda undefined bo'ladi
console.log(bobur); // undefined
console.log(window.ism); // "Bobur" (qat'iy bo'lmagan rejimda, brauzer muhitida)

Bu misol konstruktor funksiyalar bilan obyektlar yaratishda nima uchun new dan foydalanish muhimligini ko'rsatadi.

Hodisa Ishlovchilari

Brauzer muhitlarida, funksiya hodisa ishlovchisi sifatida ishlatilganda, this hodisani ishga tushirgan DOM elementiga o'rnatiladi. Bu xatti-harakat turli brauzerlar orasida bir xil va ishlovchi ichida elementga qulay kirish imkonini beradi.

document.querySelector('button').addEventListener('click', function() {
  console.log(this); // Tugma elementi
  this.textContent = 'Bosildi!';
});

// Ammo o'q funksiyalari boshqacha ishlaydi:
document.querySelector('button').addEventListener('click', () => {
  console.log(this); // Window (yoki global obyekt)
});

Oddiy funksiyalar va o'q funksiyalari o'rtasidagi bu farqni tushunish DOM hodisalari bilan ishlashda juda muhimdir.

O'q Funksiyalari va 'this'

ES6 da taqdim etilgan o'q funksiyalari thisni oddiy funksiyalardan farqli ravishda boshqaradi. Ular o'zlarining thisini bog'lamaydilar, balki o'rab turgan doiradan thisni meros qilib oladilar. Bu xatti-harakat, leksik this bog'lanishi deb ataladi, va u ham kuchli, ham murakkab bo'lishi mumkin.

const obj = {
  nom: 'Mening Obyektim',
  oddiyFunksiya: function() {
    console.log(this.nom);
  },
  oqFunksiya: () => {
    console.log(this.nom);
  },
  kechiktirilganOddiy: function() {
    setTimeout(function() {
      console.log(this.nom);
    }, 100);
  },
  kechiktirilganOq: function() {
    setTimeout(() => {
      console.log(this.nom);
    }, 100);
  }
};

obj.oddiyFunksiya(); // "Mening Obyektim"
obj.oqFunksiya(); // undefined (this global obyekt)
obj.kechiktirilganOddiy(); // undefined (this global obyekt)
obj.kechiktirilganOq(); // "Mening Obyektim"

Bu misol o'q funksiyalarining qayta chaqiruvlarda this kontekstini yo'qotish muammosini qanday hal qilishini ko'rsatadi, ammo ular ehtiyotsiz ishlatilganda kutilmagan natijalarga olib kelishi mumkinligini ham ko'rsatadi.

Aniq Bog'lanish

JavaScript thisning qiymatini aniq o'rnatish uchun metodlar taqdim etadi: call(), apply() va bind(). Bu metodlar funksiyani qanday aniqlangan yoki qayerdan chaqirilganidan qat'i nazar, belgilangan this qiymati bilan chaqirish imkonini beradi.

function salomlash(salom, tinish) {
  console.log(`${salom}, ${this.ism}${tinish}`);
}

const shaxs = { ism: 'Alisher' };

// call dan foydalanish
salomlash.call(shaxs, 'Salom', '!'); // "Salom, Alisher!"

// apply dan foydalanish
salomlash.apply(shaxs, ['Assalom', '?']); // "Assalom, Alisher?"

// bind dan foydalanish
const bog'langanSalomlash = salomlash.bind(shaxs);
bog'langanSalomlash('Hayrli kun', '.'); // "Hayrli kun, Alisher."

// oldindan o'rnatilgan argumentlar bilan bind
const salomAytAlisher = salomlash.bind(shaxs, 'Salom');
salomAytAlisher('!!'); // "Salom, Alisher!!"

Bu metodlarni tushunish ilg'or JavaScript dasturlash uchun juda muhim, ayniqsa qayta chaqiruvlar va hodisa ishlovchilari bilan ishlashda.

Yashirin Bog'lanish

Yashirin bog'lanish metod obyektda chaqirilganda sodir bo'ladi. Bu holda, this avtomatik ravishda metod chaqirilgan obyektga bog'lanadi.

const shaxs = {
  ism: 'Alisher',
  yosh: 30,
  salomlash() {
    console.log(`Salom, men ${this.ism}man va ${this.yosh} yoshdaman.`);
  }
};

shaxs.salomlash(); // "Salom, men Alisherman va 30 yoshdaman."

// Ammo buni qilsak nima bo'ladi?
const salomlash = shaxs.salomlash;
salomlash(); // "Salom, men undefinedman va undefined yoshdaman."

Oxirgi misol yashirin bog'lanish metod o'zgaruvchiga tayinlanganda va keyin chaqirilganda qanday "yo'qolishi" mumkinligini ko'rsatadi.

Leksik 'this'

Leksik this o'q funksiyalarining this kalit so'zini qanday boshqarishiga ishora qiladi. Oddiy funksiyalardan farqli o'laroq, o'q funksiyalarining o'z this konteksti yo'q.Buning o'rniga, ular o'rab turgan doiradan thisni meros qilib oladilar.

const obj = {
  nom: 'Mening Obyektim',
  oddiyMetod() {
    console.log(this.nom);
    return () => {
      console.log(this.nom);
    };
  },
  oqMetod: () => {
    console.log(this.nom);
  }
};

obj.oddiyMetod()(); // "Mening Obyektim" (ikki marta)
obj.oqMetod(); // undefined

Bu xatti-harakat o'q funksiyalarini qayta chaqiruvlar va this kontekstini saqlab qolish kerak bo'lgan metodlar uchun ayniqsa foydali qiladi.

Klasslarda 'this'

ES6 da class sintaksisi kiritilishi bilan, this konstruktor funksiyalardagi kabi ishlaydi, ammo ba'zi muhim farqlar bilan:

class Shaxs {
  constructor(ism) {
    this.ism = ism;
  }

  salomlash() {
    console.log(`Salom, men ${this.ism}man`);
  }

  static salomAyt() {
    console.log(`Salom! ${this.name}`);
  }
}

const alisher = new Shaxs('Alisher');
alisher.salomlash(); // "Salom, men Alisherman"

Shaxs.salomAyt(); // "Salom! Shaxs"

Klass metodlarida, this klass namunasiga ishora qiladi. Statik metodlarda esa, this klassning o'ziga ishora qiladi.

Umumiy Xatolar

  1. Qayta chaqiruvlarda thisni yo'qotish:
const obj = {
  nom: 'Mening Obyektim',
  kechiktirilganSalomlash() {
    setTimeout(function() {
      console.log(this.nom); // undefined
    }, 100);
  }
};
obj.kechiktirilganSalomlash();
  1. Global thisni obyekt metodining thisi deb o'ylash:
const obj = {
  nom: 'Mening Obyektim',
  salomlash: () => {
    console.log(this.nom); // undefined
  }
};
obj.salomlash();
  1. Konstruktor funksiyalar bilan new ishlatishni unutish:
function Shaxs(ism) {
  this.ism = ism;
}
const alisher = Shaxs('Alisher'); // Xato! 'new Shaxs('Alisher')' bo'lishi kerak
console.log(alisher); // undefined
console.log(window.ism); // 'Alisher' (qat'iy bo'lmagan rejimda)

Eng Yaxshi Amaliyotlar

  1. this kontekstini saqlash uchun qayta chaqiruvlarda o'q funksiyalaridan foydalaning:
const obj = {
  nom: 'Mening Obyektim',
  kechiktirilganSalomlash() {
    setTimeout(() => {
      console.log(this.nom); // 'Mening Obyektim'
    }, 100);
  }
};
  1. Global doirada thisdan foydalanishdan qoching.
  2. Funksiya uslubingizda izchil bo'ling (obyektda barcha oddiy funksiyalarni yoki barcha o'q funksiyalarini ishlating).
  3. thisni aniq o'rnatish kerak bo'lganda bind(), call() yoki apply()dan foydalaning.
  4. Metodlarga ega obyektlar yaratish uchun klasslardan foydalaning, chunki ular aniqroq tuzilishni ta'minlaydi va thisni yanada bashorat qilinadigan tarzda boshqaradi.

Ilg'or 'this' Texnikalari

Metod Qarz Olish

Siz call() yoki apply() yordamida bir obyektdan metodlarni "qarz olib" boshqa obyekt bilan ishlatishingiz mumkin:

const shaxs = {
  to'liqIsm() {
    return `${this.ism} ${this.familiya}`;
  }
};

const john = {
  ism: 'John',
  familiya: 'Doe'
};

console.log(shaxs.to'liqIsm.call(john)); // "John Doe"

Qisman Qo'llash

Siz bind()dan ba'zi argumentlari oldindan o'rnatilgan yangi funksiya yaratish uchun foydalanishingiz mumkin:

function ko'paytir(x, y) {
  return x * y;
}

const ikkilantir = ko'paytir.bind(null, 2);
console.log(ikkilantir(5)); // 10

Qat'iy Rejimda 'this'

ECMAScript 5 da kiritilgan qat'iy rejim thisning ba'zi xatti-harakatlarini o'zgartiradi:

  1. Global doirada, this global obyekt o'rniga undefined bo'ladi.
  2. Funksiya kontekstsiz chaqirilganda (ya'ni, metod sifatida emas yoki call/apply bilan emas), this global obyekt o'rniga undefined bo'ladi.
'use strict';

function showThis() {
  console.log(this);
}

showThis(); // undefined

'this'ni Disk Raskadrovka Qilish

this muammolarini disk raskadrovka qilishda:

  1. Kodingizning turli nuqtalarida console.log(this)dan foydalaning.
  2. this qiymatini ish vaqtida tekshirish uchun disk raskadrovka vositasidan foydalaning.
  3. Funksiya qaysi kontekstda chaqirilayotganini bilishingizdan xabardor bo'ling.

Tez-tez So'raladigan Savollar

  1. Savol: Nima uchun mening funksiyamdagi this undefined? Javob: Bu ko'pincha qat'iy rejimda funksiya kontekstsiz chaqirilganda sodir bo'ladi. Funksiyani obyekt metodi sifatida chaqirayotganingizga yoki kontekstni o'rnatish uchun call(), apply() yoki bind()dan foydalanayotganingizga ishonch hosil qiling.
  2. Savol: Qayta chaqiruvda thisni qanday saqlash mumkin? Javob: Siz o'rab turgan doiradan thisni meros qilib oladigan o'q funksiyasidan foydalanishingiz yoki qayta chaqiruv uchun thisni aniq o'rnatish uchun bind()dan foydalanishingiz mumkin.
  3. Savol: Nima uchun this o'q funksiyalarida boshqacha ishlaydi? Javob: O'q funksiyalarining o'z this bog'lanishi yo'q. Ular thisni o'rab turgan leksik doiradan meros qilib oladilar, bu qayta chaqiruvlar uchun foydali bo'lishi mumkin, lekin obyekt metodlari sifatida ishlatilganda kutilmagan xatti-harakatga olib kelishi mumkin.

Qo'shimcha Manbalar

  1. MDN Web Docs: this
  2. JavaScript.info: Obyekt metodlari, "this"
  3. You Don't Know JS: this & Object Prototypes
  4. JavaScript'da this ni Aniqlik bilan Tushunish va Uni O'zlashtirish
  5. JavaScript'da 'this' ning Oddiy Qoidalari
  6. JavaScript: The Definitive Guide - 8-bob: Funksiyalar
  7. Eloquent JavaScript - 6-bob: Obyektlarning Maxfiy Hayoti