Zrozumienie słowa kluczowego „this” w JavaScript

Co oznacza słowo kluczowe this w JavaScript? A jak można go praktycznie wykorzystać w swoim programie JavaScript? Oto niektóre z najczęstszych pytań, które nowicjusze, a nawet doświadczeni programiści JavaScript zadają w związku ze słowem kluczowym this.

Jeśli jesteś jednym z tych programistów, którzy zastanawiają się, o co chodzi ze słowem kluczowym this, ten artykuł jest dla Ciebie. Sprawdź, do czego to się odnosi w różnych kontekstach i zapoznaj się z kilkoma problemami, aby uniknąć nieporozumień i oczywiście błędów w kodzie.

„to” w zasięgu globalnym

W kontekście globalnym zwróci to obiekt okna, o ile znajduje się on poza funkcją. Kontekst globalny oznacza, że ​​nie umieszcza się go wewnątrz funkcji.

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

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

Jeśli uruchomisz powyższy kod, otrzymasz obiekt okna.

„to” funkcje wewnętrzne (metody)

W przypadku użycia wewnątrz funkcji odnosi się to do obiektu, z którym funkcja jest powiązana. Wyjątkiem jest użycie tej funkcji w samodzielnej funkcji, w którym to przypadku zwraca obiekt okna. Zobaczmy kilka przykładów.

W poniższym przykładzie funkcja sayName znajduje się wewnątrz obiektu me (tzn. jest metodą). W takich przypadkach odnosi się to do obiektu zawierającego funkcję.

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

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

console.log(me.sayName())

to jest obiekt me, zatem wypowiedzenie this.name w metodzie sayName jest dokładnie takie samo, jak wypowiedzenie me.name.

Innym sposobem myślenia jest to, że cokolwiek znajduje się po lewej stronie funkcji po wywołaniu, będzie to. Oznacza to, że możesz ponownie użyć funkcji sayName w różnych obiektach i za każdym razem będzie to odnosić się do zupełnie innego kontekstu.

Jak wspomniano wcześniej, zwraca to obiekt okna, gdy jest używany wewnątrz samodzielnej funkcji. Dzieje się tak, ponieważ funkcja samodzielna jest domyślnie powiązana z obiektem okna:

 function talk() {
  return this
}

talk()

Wywołanie funkcji talk() jest równoznaczne z wywołaniem window.talk(), a wszystko, co znajduje się po lewej stronie funkcji, automatycznie się nią stanie.

Na marginesie, słowo kluczowe this w funkcji zachowuje się inaczej w trybie ścisłym JavaScript (zwraca wartość niezdefiniowaną). Należy o tym także pamiętać, gdy używasz bibliotek interfejsu użytkownika korzystających z trybu ścisłego (np. React).

Używanie „tego” z funkcją Function.bind()

Mogą zaistnieć sytuacje, w których nie można po prostu dodać funkcji do obiektu jako metody (jak w ostatniej sekcji).

Być może obiekt nie jest Twój i wyciągasz go z biblioteki. Obiekt jest niezmienny, więc nie można go po prostu zmienić. W takich przypadkach nadal możesz wykonać instrukcję funkcji oddzielnie od obiektu, używając metody Function.bind().

W poniższym przykładzie funkcja sayName nie jest metodą obiektu me, ale mimo to powiązano ją za pomocą funkcji bind():

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

const me = {
  name: "Kingsley"
}

const meTalk = sayName.bind(me)

meTalk()

Jakikolwiek obiekt, który przekażesz do bind(), zostanie użyty jako wartość this w wywołaniu tej funkcji.

Podsumowując, możesz użyć metody bind() na dowolnej funkcji i przekazać ją w nowym kontekście (obiekt). I ten obiekt nadpisze znaczenie this wewnątrz tej funkcji.

Używanie „tego” z funkcją Function.call()

A co, jeśli nie chcesz zwracać zupełnie nowej funkcji, a raczej po prostu wywołać funkcję po powiązaniu jej z kontekstem? Rozwiązaniem jest metoda call():

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

const me = {
  name: "Kingsley"
}

sayName.call(me)

Metoda call() natychmiast wykonuje funkcję, zamiast zwracać inną funkcję.

Jeśli funkcja wymaga parametru, możesz przekazać go metodą call(). W poniższym przykładzie przekazujesz język do funkcji sayName(), dzięki czemu możesz go użyć do warunkowego zwracania różnych komunikatów:

 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')

Jak widać, możesz po prostu przekazać do funkcji dowolny parametr jako drugi argument metody call(). Możesz także przekazać dowolną liczbę parametrów.

Metoda Apply() jest bardzo podobna do metody call() i bind(). Jedyna różnica polega na tym, że w przypadku metody call() przekazuje się wiele argumentów, oddzielając je przecinkiem, natomiast w przypadku metody Apply() przekazuje się wiele argumentów wewnątrz tablicy.

Podsumowując, metody bind(), call() i Apply() umożliwiają wywoływanie funkcji z zupełnie innym obiektem bez żadnego związku między nimi (tj. funkcja nie jest metodą na obiekcie).

„To” Funkcje konstruktora wewnętrznego

Jeśli wywołasz funkcję z nowym słowem kluczowym, utworzy ona obiekt this i zwróci go:

 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

W powyższym kodzie utworzyłeś trzy różne obiekty za pomocą tej samej funkcji. Słowo kluczowe new automatycznie tworzy powiązanie między tworzonym obiektem a słowem kluczowym this wewnątrz funkcji.

„To” wewnętrzne funkcje wywołania zwrotnego

Funkcje wywołania zwrotnego różnią się od zwykłych funkcji. Funkcje wywołania zwrotnego to funkcje przekazywane innej funkcji jako argument, dzięki czemu można je wykonać natychmiast po zakończeniu wykonywania funkcji głównej.

Słowo kluczowe this odnosi się do zupełnie innego kontekstu, gdy jest używane w funkcjach wywołania zwrotnego:

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

const me = new person("Kingsley")

Po jednej sekundzie wywołania funkcji konstruktora osoby i utworzenia nowego obiektu me zostanie zarejestrowany obiekt window jako wartość this. Zatem użyte w funkcji wywołania zwrotnego odnosi się do obiektu okna, a nie do „skonstruowanego” obiektu.

Można to naprawić na dwa sposoby. Pierwsza metoda polega na użyciu funkcji bind() w celu powiązania funkcji osoby z nowo skonstruowanym obiektem:

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

const me = new person("Kingsley")

W przypadku powyższej modyfikacji this w wywołaniu zwrotnym będzie wskazywało to samo, co funkcja konstruktora (obiekt me).

Drugim sposobem rozwiązania tego problemu w funkcjach wywołania zwrotnego jest użycie funkcji strzałkowych.

„To” Funkcje strzałek wewnętrznych

Funkcje strzałkowe różnią się od zwykłych funkcji. Możesz ustawić funkcję wywołania zwrotnego jako funkcję strzałkową. Dzięki funkcjom strzałkowym nie potrzebujesz już funkcji bind(), ponieważ automatycznie łączy się ona z nowo skonstruowanym obiektem:

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

const me = new person("Kingsley")

Dowiedz się więcej o JavaScript

Dowiedziałeś się już wszystkiego o słowie kluczowym „this” i jego znaczeniu we wszystkich różnych kontekstach w JavaScript. Jeśli dopiero zaczynasz przygodę z JavaScriptem, odniesiesz ogromne korzyści, poznając wszystkie podstawy JavaScriptu i jego działanie.