JavaScript `this` ključna riječ + 5 obvezujućih ključnih pravila objašnjena za JS početnike

JavaScript thisključ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 thisključ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 thisključnoj riječi dok se funkcija ne pozove.

Korištenje thisse može kategorizirati u pet različitih bindingaspekata. U ovom ćemo članku s primjerima naučiti svih pet aspekata.

Prvo, što je obvezujuće?

U JavaScriptu, a Lexical Environmentje mjesto gdje je vaš kod fizički napisan. U primjeru u nastavku naziv varijable nalazi se lexicallyunutar funkcije sayName().

function sayName() { let name = 'someName'; console.log('The name is, ', name); }

Referent se Execution Contextodnosi 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. Bindingu JavaScript-u znači bilježenje identifikatora (varijable i imena funkcije) u određenom Zapisu o okolišu.

Napomena: Bindingpomaže u pridruživanju identifikatora (varijable i imena funkcije) s thisključ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 thisključ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 thisje obvezujuće.

Pogledajmo primjer kako bismo ga bolje razumjeli.

let user = { name: 'Tapas', address: 'freecodecamp', getName: function() { console.log(this.name); } }; user.getName();

Ovdje thisje vezan za korisnički objekt. To znamo jer lijevo od operatora točke (.) Uz funkciju getName()vidimo userobjekt. 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 tomi jerry. Te smo predmete ukrasili (poboljšali) pričvršćivanjem metode tzv logName().

Primijetite da tom.logName()se tomobjekt kada se pozivamo nalazi lijevo od operatora točke (.) Uz funkciju logName(). Tako thisje vezan za tomobjekt i bilježi vrijednost tom (ovdje this.nameje 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 thisovdje? 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.namebi 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(), and bind() play a big role here.
  • When a function is invoked with the new keyword, the this 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 or new, then this is bound to the window(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 functions. 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.