Kluczowe słowo this
odnosi się do wartości obiektu powiązanego z funkcją w momencie jej wywołania, co oznacza, że jej wartość jest inna w zależności od tego, czy funkcja jest wywoływana jako metoda, funkcja samodzielna czy konstruktor.
Gdy funkcja zostanie wywołana, tworzy ona instancję słowa kluczowego this
jako odwołania do obiektu zawierającego tę funkcję, co daje dostęp do właściwości i metod zdefiniowanych w jej zakresie.
Praca z wartością this
jest w pewnym sensie podobna do pracy z wartością zadeklarowaną za pomocą funkcji const
. Podobnie jak w przypadku stałych, zmiennej this
nie można usunąć ani zmienić jej wartości, ale można modyfikować metody i właściwości obiektu, który zawiera słowo kluczowe this
.
Globalne wiązanie
Poza funkcją lub kontekstem obiektu this
odnosi się do właściwości globalThis
, która jest odwołaniem do obiektu globalnego w większości środowisk JavaScript. W kontekście skryptu działającego w przeglądarce obiekt globalny to obiekt window
:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
W Node.js globalThis
to obiekt global
:
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}
Poza trybem ścisłym this
odwołuje się też do obiektu globalnego w ramach samodzielnej funkcji, ponieważ nadrzędny obiekt Window
jest obiektem, który „posiada” te funkcje.
function myFunction() {
console.log( this );
}
myFunction();
> Window {...}
(function() {
console.log( this );
}());
> Window {...}
W trybie ścisłym funkcja this
ma wartość undefined
w ramach funkcji samodzielnej:
(function() {
"use strict";
console.log( this );
}());
> undefined
Przed wprowadzeniem trybu ścisłego wartość null
lub undefined
w obiekcie this
była zastępowana przez odwołanie do obiektu globalnego. Z powodu tego zachowania z upływem czasu wiązanie globalne jest czasami określane jako „wiązanie domyślne”.
Powiązanie niejawne
Gdy funkcja jest wywoływana jako metoda obiektu, instancja this
w tej metodzie odnosi się do obiektu zawierającego metodę, co zapewnia dostęp do metod i właściwości znajdujących się obok niej:
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
Może się wydawać, że wartość this
zależy od sposobu zdefiniowania funkcji i otaczającego ją obiektu. Zamiast tego kontekstem wartości this
jest bieżący kontekst wykonania. W tym przypadku kontekst wykonania polega na tym, że obiekt myObject
wywołuje metodę myMethod
, więc myObject
to wartość dla this
. W kontekście poprzednich przykładów może się to wydawać kwestią techniczną, ale w przypadku bardziej zaawansowanego korzystania z elementu this
jest to istotne rozróżnienie.
Ogólnie rzecz biorąc, używaj funkcji this
w taki sposób, aby nie wymagać od otaczającego kodu określonej struktury. Wyjątkiem od tej zasady są funkcje strzałki w ES5.
this
w funkcjach strzałek
W funkcjach strzałkithis
jest interpretowany jako wiązanie w otoczeniu otaczającym leksykalne. Oznacza to, że
this
w funkcji strzałki odnosi się do wartości this
w najbliższym kontekście otaczającym tę funkcję:
let myObject = {
myMethod() { console.log( this ); },
myArrowFunction: () => console.log( this ),
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
myObject.myArrowFunction();
> Window {...}
W poprzednim przykładzie funkcja myObject.myMethod()
zapisuje myObject
jako obiekt, który „posiada” tę metodę, ale funkcja myObject.myArrowFunction()
zwraca globalThis
(lub undefined
), ponieważ instancja this
wewnątrz funkcji strzałki odnosi się do najwyższego zakresu otaczającego ją kodu.
W tym przykładzie funkcja strzałki myEnclosingMethod
jest tworzona w obiekcie, który ją zawiera, gdy jest wykonywana. Występujący w funkcji strzałki element this
odwołuje się teraz do wartości elementu this
w otaczającym środowisku, czyli w metodie, która zawiera funkcję strzałki. Ponieważ wartość this
w funkcji myEnclosingMethod
odnosi się do funkcji myObject
, po zdefiniowaniu funkcji strzałki wartość this
w niej odnosi się też do funkcji myObject
:
let myObject = {
myMethod() { console.log( this ); },
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
Wyraźne wiązanie
Wiązanie domyślne obsługuje większość przypadków użycia dotyczących this
. Czasami jednak wartość this
może reprezentować konkretny kontekst wykonania zamiast założenia. Przykładowy, choć nieco przestarzały, przykład to praca z funkcją this
w funkcji wywołania zwrotnego setTimeout
, ponieważ to wywołanie zwrotne ma unikalny kontekst wykonania:
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
myObject.myMethod();
> "This is my string."
setTimeout( myObject.myMethod, 100 );
> undefined
Chociaż ten konkretny brak funkcji setTimeout
został już rozwiązany przez inne funkcje, podobne problemy z „utratą” wartości this
zostały rozwiązane przez utworzenie wyraźnego odwołania do wartości this
w ramach odpowiedniego kontekstu. W starszych bazach kodu możesz czasem zauważyć, że this
jest przypisywany do zmiennej za pomocą identyfikatorów takich jak that
, self
lub _this
. To typowe konwencje identyfikatorów w przypadku zmiennych zawierających wartość przekazaną za pomocą parametru this
.
Gdy wywołujesz funkcję za pomocą metod call()
, bind()
lub apply()
, funkcja this
wyraźnie odwołuje się do wywoływanego obiektu:
let myFunction = function() {
console.log( this.myValue );
}
let myObject = {
"myValue" : "This is my string."
};
myFunction.call( myObject );
> "This is my string."
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."
Wiązanie jawne zastępuje wartość this
określoną przez wiązanie domyślne.
let myObject = {
"myValue" : "This string sits alongside myMethod.",
myMethod() {
console.log( this.myValue );
}
};
let myOtherObject = {
"myValue" : "This is a string in another object entirely.",
};
myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."
Jeśli funkcja jest wywoływana w sposób, który ustawia wartość this
na undefined
lub null
, ta wartość jest zastępowana przez globalThis
poza trybem ścisłym:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
Podobnie, jeśli funkcja jest wywoływana w sposób, który powoduje, że this
ma wartość prymitywną, ta wartość jest zastępowana obiektem owijającym wartość prymitywną poza trybem ścisłym:
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> Number { 10 }
W trybie rygorystycznym przekazana wartość this
nie jest w żaden sposób zmuszana do obiektu, nawet jeśli jest to wartość prymitywna, null
lub undefined
:
"use strict";
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> 10
myFunction.call( null );
> null
new
powiązanie
Gdy klasa jest używana jako konstruktor za pomocą słowa kluczowego new
, this
odnosi się do nowo utworzonej instancji:
class MyClass {
myString;
constructor() {
this.myString = "My string.";
}
logThis() {
console.log( this );
}
}
const thisClass = new MyClass();
thisClass.logThis();
> Object { myString: "My string." }
Podobnie wartość this
wewnątrz konstruktora wywoływanego za pomocą new
odnosi się do tworzonego obiektu:
function MyFunction() {
this.myString = "My string.";
this.logThis = function() {
console.log( this );
}
}
const myObject = new MyFunction();
myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }
Wiązanie modułu obsługi zdarzeń
W kontekście metod obsługi zdarzeń wartość this
odwołuje się do obiektu, który ją wywołuje. W funkcji wywołania zwrotnego modułu obsługi zdarzeń this
odwołuje się do elementu powiązanego z tym modułem:
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
Gdy użytkownik wejdzie w interakcję z elementem button
w poprzednim fragmencie kodu, wynikiem jest obiekt element zawierający element <button>
:
> Button {}
Gdy funkcja strzałki jest używana jako wywołanie zwrotne detektora zdarzeń, wartość this
jest ponownie dostarczana przez najbliższy kontekst wykonania. Oznacza to, że na najwyższym poziomie this
w ramach funkcji wywołania zwrotnego w obsługach zdarzeń jest globalThis
:
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
Podobnie jak w przypadku innych obiektów, gdy używasz metod call()
, bind()
lub apply()
, aby odwoływać się do funkcji wywołania zwrotnego detektora zdarzeń, this
odwołuje się do obiektu w wyraźny sposób:
let button = document.querySelector( "button" );
let myObject = {
"myValue" : true
};
function handleClick() {
console.log( this );
}
button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }
Sprawdź swoją wiedzę
Jaki jest obiekt globalny, do którego odwołuje się this
, gdy jest używany poza funkcją lub kontekstem obiektu w przypadku skryptu działającego w przeglądarce?
window
undefined
browser