JavaScript this
ključna riječ jedan je od najtežih aspekata jezika koji se može shvatiti. Ali to je presudno važno za pisanje naprednijeg JavaScript koda.
U JavaScript-u this
ključna riječ omogućuje nam:
- Ponovna upotreba funkcija u različitim kontekstima i
- Utvrdite na koji se objekt usredotočiti kada se metoda pozove.
Što se tiče this
, važno je postaviti pitanje gdje se funkcija poziva. Jer ne znamo što je u this
ključnoj riječi dok se funkcija ne pozove.
Korištenje this
se može kategorizirati u pet različitih binding
aspekata. U ovom ćemo članku s primjerima naučiti svih pet aspekata.
Prvo, što je obvezujuće?
U JavaScriptu, a Lexical Environment
je mjesto gdje je vaš kod fizički napisan. U primjeru u nastavku naziv varijable nalazi se lexically
unutar funkcije sayName()
.
function sayName() { let name = 'someName'; console.log('The name is, ', name); }
Referent se Execution Context
odnosi na kôd koji je trenutno pokrenut i na sve ostalo što pomaže u njegovom izvođenju. Dostupno je puno leksičkih okruženja, ali onim koje se trenutno izvodi upravlja kontekst izvršenja .

Svaki kontekst izvršenja sadrži Environment Record
. Binding
u JavaScript-u znači bilježenje identifikatora (varijable i imena funkcije) u određenom Zapisu o okolišu.
Napomena: Binding
pomaže u pridruživanju identifikatora (varijable i imena funkcije) s this
ključnom riječi za execution context
.
Ne brinite ako vam je sada ovo malo teško razumjeti. Kako ćete nastaviti, bolje ćete shvatiti.
Pravilo # 1: Kako djeluje implicitno vezivanje JavaScripta
Implicitno vezivanje pokriva većinu slučajeva korištenja this
ključne riječi.
U implicitnom vezivanju trebate provjeriti što je lijevo od operatora točke (.) Uz funkciju u vrijeme poziva. To određuje ono za što this
je obvezujuće.
Pogledajmo primjer kako bismo ga bolje razumjeli.
let user = { name: 'Tapas', address: 'freecodecamp', getName: function() { console.log(this.name); } }; user.getName();
Ovdje this
je vezan za korisnički objekt. To znamo jer lijevo od operatora točke (.) Uz funkciju getName()
vidimo user
objekt. Tako this.name
će i prijaviti Tapas u konzolu.
Pogledajmo još jedan primjer za bolje razumijevanje ovog koncepta:
function decorateLogName(obj) { obj.logName = function() { console.log(this.name); } }; let tom = { name: 'Tom', age: 7 }; let jerry = { name: 'jerry', age: 3 }; decorateLogName(tom); decorateLogName(jerry); tom.logName(); jerry.logName();
U ovom primjeru imamo dva objekta tom
i jerry
. Te smo predmete ukrasili (poboljšali) pričvršćivanjem metode tzv logName()
.
Primijetite da tom.logName()
se tom
objekt kada se pozivamo nalazi lijevo od operatora točke (.) Uz funkciju logName()
. Tako this
je vezan za tom
objekt i bilježi vrijednost tom (ovdje this.name
je jednaka tomu ). Isto vrijedi i kada jerry.logName()
se pozove.
Pravilo br. 2: Kako JavaScript eksplicitno vezivanje djeluje
Vidjeli smo da JavaScript stvara okruženje za izvršavanje koda koji pišemo. Vodi računa o stvaranju memorije za varijable, funkcije, objekte i tako dalje u fazi stvaranja . Napokon izvršava kod u fazi izvršenja . Ovo posebno okruženje naziva se Execution Context
.
U JavaScript aplikaciji može biti mnogo takvih okruženja (konteksti izvršenja). Svaki kontekst izvršenja djeluje neovisno od ostalih.
Ali ponekad ćemo možda htjeti koristiti stvari iz jednog konteksta izvršenja u drugom. Tu na scenu stupa eksplicitno vezivanje.
U eksplicitnom vezivanju možemo pozvati funkciju s objektom kada je funkcija izvan konteksta izvršenja objekta.
Postoje tri vrlo posebne metode call()
, apply()
i bind()
koje nam pomažu u postizanju eksplicitnog vezanja.
Kako funkcionira JavaScript call()
metoda
S ovom call()
metodom, kontekst s kojim se funkcija mora pozvati prosljeđuje se kao parametar call()
. Pogledajmo kako to funkcionira na primjeru:
let getName = function() { console.log(this.name); } let user = { name: 'Tapas', address: 'Freecodecamp' }; getName.call(user);
Ovdje se call()
metoda poziva na funkciju koja se naziva getName()
. getName()
Funkcija samo prijavljuje this.name
. Ali što je this
ovdje? To se određuje onim što je proslijeđeno call()
metodi.
Ovdje this
će se vezati za korisnički objekt jer smo call()
metodi proslijedili korisnika kao parametar . Tako this.name
bi trebao zapisati vrijednost svojstva imena korisničkog objekta, to je Tapas .
U gornjem primjeru proslijedili smo samo jedan argument call()
. Ali također možemo proslijediti više argumenata call()
, poput ovog:
let getName = function(hobby1, hobby2) { console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2); } let user = { name: 'Tapas', address: 'Bangalore' }; let hobbies = ['Swimming', 'Blogging']; getName.call(user, hobbies[0], hobbies[1]);
Ovdje smo call()
metodi proslijedili više argumenata . Prvi argument mora biti kontekst objekta s kojim se funkcija mora pozvati. Ostali parametri mogu biti samo vrijednosti koje treba koristiti.
Ovdje prenosim Plivanje i Bloganje kao dva parametra getName()
funkciji.
Jeste li ovdje primijetili bolnu točku? U slučaju a call()
, argumente treba prosljeđivati jedan po jedan - što nije pametan način postupanja! Tu dolazi do izražaja naša sljedeća metoda apply()
.
Kako funkcionira JavaScript apply()
metoda
Ovaj užurbani način prosljeđivanja argumenata call()
metodi može se riješiti drugom alternativnom metodom koja se naziva apply()
. To je potpuno isto kao i, call()
ali omogućuje vam jednostavnije prosljeđivanje argumenata. Pogledaj:
let getName = function(hobby1, hobby2) { console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2); } let user = { name: 'Tapas', address: 'Bangalore' }; let hobbies = ['Swimming', 'Blogging']; getName.apply(user, hobbies);
Ovdje smo u mogućnosti proslijediti niz argumenata, što je mnogo prikladnije od njihova prosljeđivanja jednog po jednog.
Savjet: Kada imate samo jedan argument vrijednosti ili nema argumenata vrijednosti za prosljeđivanje, upotrijebite call()
. Kad imate više argumenata vrijednosti za prosljeđivanje, upotrijebite apply()
.
Kako funkcionira JavaScript bind()
metoda
bind()
Metoda je slična call()
metodi, ali s jednom razlikom. Za razliku od call()
metode izravnog pozivanja funkcije, bind()
vraća potpuno novu funkciju i mi je možemo pozvati.
let getName = function(hobby1, hobby2) { console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2); } let user = { name: 'Tapas', address: 'Bangalore' }; let hobbies = ['Swimming', 'Blogging']; let newFn = getName.bind(user, hobbies[0], hobbies[1]); newFn();
Here the getName.bind()
doesn't invoke the function getName()
directly. It returns a new function, newFn
and we can invoke it as newFn()
.
Rule #3: The JavaScript new
Binding
A new
keyword is used to create an object from the constructor function.
let Cartoon = function(name, animal) { this.name = name; this.animal = animal; this.log = function() { console.log(this.name + ' is a ' + this.animal); } };
You can create objects using the new
keyword like this:
let tom = new Cartoon('Tom', 'Cat'); let jerry = new Cartoon('Jerry', 'Mouse');
The constructor function's new binding rule states that, when a function is invoked with the new keyword, the this keyword inside the function binds to the new object being constructed.
Sounds complex? Ok, let's break it down. Take this line,
let tom = new Cartoon('Tom', 'Cat');
Here the function Cartoon is invoked with the new
keyword. So this
will be bound to the new object being created here, which is tom.
Rule #4: JavaScript Global Object Binding
What do you think will be the output of the code below? What is this
binding to here?
let sayName = function(name) { console.log(this.name); }; window.name = 'Tapas'; sayName();
If the this
keyword is not resolved with any of the bindings, implicit
, explicit
or new
, then the this
is bound to the window(global)
object.
There is one exception though. JavaScript strict mode does not allow this default binding.
"use strict"; function myFunction() { return this; }
In the above case, this
is undefined.
Rule #5: HTML Event Element Binding in JavaScript
In HTML event handlers, this
binds to the HTML elements that receive the event.
Click Me!
The is the output log in the console when you click on the button:
"Click Me!"
You can change the button style using the this
keyword, like this:
Click Me!
But be mindful when you call a function on the button click and use this
inside that function.
Click Me!
and the JavaScript:
function changeColor() { this.style.color='teal'; }
The above code won't work as expected. As we have seen in the Rule 4, here this
will be bound to the global object (in the 'non-strict' mode) where there is no style object to set the color.
In Summary
To summarize,
- In the case of implicit binding,
this
binds to the object to the left of the dot(.) operator. - In the case of explicit binding, we can call a function with an object when the function is outside of the execution context of the object. The methods
call()
,apply()
, andbind()
play a big role here. - When a function is invoked with the
new
keyword, thethis
keyword inside the function binds to the new object being constructed. - When the
this
keyword is not resolved with any of the bindings,implicit
,explicit
ornew
, thenthis
is bound to thewindow(global)
object. In JavaScript's strict mode,this
will be undefined. - In HTML event handlers,
this
binds to the HTML elements that receive the event.
There is one more case where this
behaves differently, such as with ES6 arrow function
s. We will take a look at that in a future article.
I hope you found this article insightful. You may also like,
- JavaScript Hoisting Internals
- Understanding JavaScript Execution Context like never before
- JavaScript Scope Fundamentals with Tom and Jerry
- Understanding JavaScript Closure with example
If this article was useful, please share it so others can read it as well. You can @ me on Twitter (@tapasadhikary) with comments, or feel free to follow me.