A JavaScript `this` kulcsszó + 5 kulcsfontosságú kötési szabály magyarázata JS kezdőknek

A JavaScript thiskulcsszava az egyik legnehezebben felfogható nyelv. De kritikus fontosságú a fejlettebb JavaScript-kód írásakor.

A JavaScript-ben a thiskulcsszó lehetővé teszi számunkra, hogy:

  • Újrafelhasználási funkciók különböző kontextusokban, és
  • Határozza meg, melyik objektumra kell összpontosítania, amikor egy metódust meghívnak.

Amikor rákerül a thiskérdés, fontos feltenni, hogy a függvény hol merül fel. Mivel thisa függvény meghívásáig nem tudjuk, mi van a kulcsszóban.

A használata thisöt különböző bindingaspektusba sorolható . Ebben a cikkben mind az öt szempontot megismerjük példákkal.

Először: Mi a kötés?

A JavaScript-ben Lexical Environmenta kódot fizikailag írják. Az alábbi példában a változó neve lexicallya függvényen belül található sayName().

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

Az Execution Contextegy a jelenleg futó kódra és minden másra utal, amely segíti a futtatást. Sok lexikális környezet érhető el, de a jelenleg futót az Execution Context kezeli .

A végrehajtási kontextus mindegyike tartalmaz egy Environment Record. Bindinga JavaScript azt jelenti, hogy az azonosítót (változó és függvénynév) rögzítjük egy adott környezeti rekordba.

Megjegyzés: Bindingsegít társítani az azonosítót (változó és függvény neve) thisaz an kulcsszavához execution context.

Ne aggódjon, ha ezt most egy kicsit nehéz megértenie. Jobban meg fogja fogni, ahogy haladunk.

1. szabály: Hogyan működik a JavaScript implicit kötése

Az implicit kötés lefedi a thiskulcsszó kezelésének legtöbb felhasználási esetét .

Az implicit kötésben ellenőrizni kell, hogy mi van a pont (.) Operátor bal oldalán egy függvény mellett, meghíváskor. Ez határozza meg, hogy mi thiskötelező.

Nézzünk meg egy példát, hogy jobban megértsük.

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

Itt thisa felhasználói objektumhoz van kötve. Ezt azért tudjuk, mert a függvénnyel szomszédos dot (.) Operátor bal oldalán getName()látjuk az userobjektumot. Tehát this.namenaplózni fogja a Tapast a konzolon.

Nézzünk meg egy másik példát a koncepció jobb megértéséhez:

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();

Ebben a példában két objektumunk van, tomés jerry. Díszítettük (továbbfejlesztettük) ezeket a tárgyakat az úgynevezett módszer csatolásával logName().

Figyeljük meg, hogy amikor meghívjuk tom.logName(), az tomobjektum a függvény mellett található pont (.) Operátor bal oldalán található logName(). Tehát thisaz tomobjektumhoz van kötve, és naplózza a tom értéket ( this.nameitt megegyezik a tommal). Ugyanez vonatkozik jerry.logName()a meghívásra is.

2. szabály: Hogyan működik a JavaScript explicit kötése

Láttuk, hogy a JavaScript környezetet teremt az általunk írt kód végrehajtásához. Gondoskodik a változók, függvények, objektumok stb. Memóriájának létrehozásáról a létrehozás fázisában . Végül végrehajtja a kódot a végrehajtási szakaszban . Ezt a különleges környezetet nevezzük Execution Context.

Számos ilyen környezet (végrehajtási környezet) lehet egy JavaScript alkalmazásban. Minden végrehajtási környezet függetlenül működik a többitől.

De időnként előfordulhat, hogy az egyik végrehajtási kontextusból származó dolgokat fel akarjuk használni a másikban. Itt jön létre a kifejezett kötés.

Kifejezett kötésben funkciót hívhatunk egy objektummal, ha a függvény kívül esik az objektum végrehajtási környezetén.

Három nagyon speciális módszer létezik call(), apply()és bind()ezek segítenek bennünket a kifejezett kötelező érvényben.

Hogyan call()működik a JavaScript módszer

A call()módszerrel az a kontextus, amellyel a függvényt meg kell hívni, paraméterként átkerül a call(). Nézzük meg, hogyan működik egy példával:

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

Itt a call()metódust az úgynevezett függvényre hívják meg getName(). A getName()függvény csak naplóz this.name. De mi van thisitt? Ezt meghatározza az, amit átadtak a call()módszernek.

Itt thisfog kötődni a felhasználói objektumhoz, mert a felhasználót paraméterként átadtuk a call()metódusnak. Tehát this.namenaplóznia kell a felhasználói objektum, vagyis a Tapas név tulajdonságának értékét .

A fenti példában csak egy érvet adtunk át call(). De több érvet is átadhatunk call(), például:

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]);

Itt több argumentumot adtunk át a call()metódusnak. Az első argumentumnak az objektum kontextusának kell lennie, amellyel a függvényt meg kell hívni. Más paraméterek csak használható értékek lehetnek.

Itt átadom az úszás és a blogolás két paraméterét a getName()függvénynek.

Észrevett itt egy fájdalom pontot? A esetén call()az érveket egyenként kell átadni - ami nem intelligens módja a dolgoknak! Itt apply()jön képbe a következő módszerünk .

Hogyan apply()működik a JavaScript módszer

Az argumentumok call()metódusoknak ez a mozgalmas módja megoldható egy másik alternatív módszerrel, az úgynevezett módszerrel apply(). Pontosan megegyezik azzal, call()de lehetővé teszi az érvek kényelmesebb átadását. Nézd meg:

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

Itt érvek tömbjét adhatjuk át, ami sokkal kényelmesebb, mint egyesével továbbadni.

Tipp: Ha csak egy értéket érv vagy nincs értéke érvek át, használata call(). Ha több érték argumentumot kell átadnia, használja a apply().

Hogyan bind()működik a JavaScript módszer

A bind()módszer hasonló a call()módszerhez, de egy különbséggel. A call()függvény közvetlen meghívásának módszerével ellentétben bind()egy teljesen új függvényt ad vissza, és helyette ezt meghívhatjuk.

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.