Розуміння «це» ключового слова JavaScript

Що означає це ключове слово в JavaScript? І як ви можете використовувати його практично у своїй програмі JavaScript? Це деякі з поширених запитань, які задають новачки та навіть деякі досвідчені розробники JavaScript щодо ключового слова this.

Якщо ви один із тих розробників, яким цікаво, що таке це ключове слово, тоді ця стаття для вас. Дослідіть, що це стосується в різних контекстах, і ознайомтеся з деякими помилками, щоб уникнути плутанини, і, звичайно, помилок у вашому коді.

«це» в глобальному масштабі

У глобальному контексті це повертатиме об’єкт вікна, доки він знаходиться поза функцією. Глобальний контекст означає, що ви не розміщуєте його всередині функції.

 if(true) {
  console.log(this)
}

let i = 2
while(i < 10) {
  console.log(this)
  i++
}

Якщо ви запустите наведений вище код, ви отримаєте об’єкт window.

«це» внутрішні функції (методи)

При використанні всередині функцій це стосується об’єкта, до якого прив’язана функція. Винятком є ​​випадки, коли ви використовуєте це в автономній функції, і в цьому випадку він повертає об’єкт вікна. Давайте розглянемо кілька прикладів.

У наступному прикладі функція sayName знаходиться всередині об’єкта me (тобто це метод). У подібних випадках це стосується об’єкта, що містить функцію.

  
function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley",
  sayName: sayName
}

console.log(me.sayName())

це об’єкт me, тому сказати this.name у методі sayName точно так само, як me.name.

Інший спосіб подумати про це: все, що знаходиться ліворуч від функції під час виклику, буде цим. Це означає, що ви можете повторно використовувати функцію sayName в різних об’єктах, і це кожного разу посилатиметься на зовсім інший контекст.

Тепер, як згадувалося раніше, це повертає об’єкт вікна, якщо він використовується всередині автономної функції. Це пояснюється тим, що окрема функція за замовчуванням прив’язана до об’єкта вікна:

 function talk() {
  return this
}

talk()

Виклик talk() — це те саме, що виклик window.talk(), і все, що знаходиться ліворуч від функції, автоматично стане цим.

До речі, ключове слово this у функції поводиться інакше в строгому режимі JavaScript (воно повертає undefined). Про це також слід пам’ятати, коли ви використовуєте бібліотеки інтерфейсу користувача, які використовують строгий режим (наприклад, React).

Використання «this» із Function.bind()

Можуть бути випадки, коли ви не можете просто додати функцію до об’єкта як метод (як у попередньому розділі).

Можливо, об’єкт не ваш, і ви витягуєте його з бібліотеки. Об’єкт незмінний, тому його не можна просто змінити. У подібних випадках ви можете виконати оператор функції окремо від об’єкта за допомогою методу Function.bind().

У наступному прикладі функція sayName не є методом для об’єкта me, але ви все одно зв’язали її за допомогою функції bind():

 function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley"
}

const meTalk = sayName.bind(me)

meTalk()

Будь-який об’єкт, який ви передаєте в bind(), буде використано як значення this у цьому виклику функції.

Таким чином, ви можете використовувати bind() для будь-якої функції та передати новий контекст (об’єкт). І цей об’єкт перезапише значення this у цій функції.

Використання «this» із Function.call()

Що робити, якщо ви не хочете повертати цілком нову функцію, а просто викликаєте функцію після прив’язування її до контексту? Рішенням для цього є метод call():

 function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley"
}

sayName.call(me)

Метод call() негайно виконує функцію замість повернення іншої функції.

Якщо для функції потрібен параметр, ви можете передати його за допомогою методу call(). У наступному прикладі ви передаєте мову функції sayName(), тож ви можете використовувати її для умовного повернення різних повідомлень:

 function sayName(lang) {
  if (lang === "en") {
    return `My name is ${this.name}`
  } else if (lang === "it") {
    return `Io sono ${this.name}`
  }
}

const me = {
  name: "Kingsley"
}

sayName.call(me, 'en')
sayName.call(me, 'it')

Як бачите, ви можете просто передати будь-який параметр, який хочете, у функцію як другий аргумент методу call(). Ви також можете передати скільки завгодно параметрів.

Метод apply() дуже схожий на call() і bind(). Єдина відмінність полягає в тому, що ви передаєте кілька аргументів, розділяючи їх комою за допомогою call(), тоді як ви передаєте кілька аргументів усередині масиву за допомогою apply().

Підводячи підсумок, bind(), call() і apply() дозволяють вам викликати функції з зовсім іншим об’єктом без будь-якого зв’язку між ними (тобто функція не є методом об’єкта).

“this” Внутрішні функції конструктора

Якщо ви викликаєте функцію з новим ключовим словом, вона створює об’єкт this і повертає його:

 function person(name){
  this.name = name
}

const me = new person("Kingsley")
const her = new person("Sarah")
const him = new person("Jake")

me.name
her.name
him.name

У наведеному вище коді ви створили три різні об’єкти з однієї функції. Ключове слово new автоматично створює прив’язку між об’єктом, який створюється, і ключовим словом this у функції.

“this” внутрішні функції зворотного виклику

Функції зворотного виклику відрізняються від звичайних функцій. Функції зворотного виклику — це функції, які ви передаєте іншій функції як аргумент, тому вони можуть бути виконані відразу після завершення виконання основної.

Ключове слово this посилається на зовсім інший контекст, коли використовується в функціях зворотного виклику:

 function person(name){
  this.name = name
  setTimeout(function() {
    console.log(this)
  }, 1000)
}

const me = new person("Kingsley")

Через одну секунду після виклику функції-конструктора person і створення нового об’єкта me об’єкт window буде зареєстровано як значення this. Отже, коли використовується у функції зворотного виклику, це стосується об’єкта вікна, а не «сконструйованого» об’єкта.

Виправити це можна двома способами. Перший метод використовує bind() для прив’язки функції person до новоствореного об’єкта:

 function person(name){
  this.name = name
  setTimeout(function() {
    console.log(this)
  }.bind(this), 1000)
}

const me = new person("Kingsley")

З наведеною вище модифікацією this у зворотному виклику вказуватиме на те саме this, що й функція-конструктор (об’єкт me).

Другий спосіб вирішити цю проблему у функціях зворотного виклику — це використовувати функції зі стрілками.

Функції внутрішньої стрілки «це».

Функції зі стрілками відрізняються від звичайних функцій. Ви можете зробити функцію зворотного виклику функцією стрілки. З функціями зі стрілками вам більше не потрібен bind(), оскільки він автоматично прив’язується до щойно створеного об’єкта:

 function person(name){
  this.name = name
  setTimeout(() => {
    console.log(this)
  }, 1000)
}

const me = new person("Kingsley")

Дізнайтеся більше про JavaScript

Ви дізналися все про ключове слово «this» і його значення в різних контекстах JavaScript. Якщо ви новачок у JavaScript, вам буде дуже корисно вивчити всі основи JavaScript і його роботу.