To słowo kluczowe

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.

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ą newodnosi 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ń thisodwoł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ń, thisodwoł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?

Obiekt window
Obiekt undefined
Obiekt browser