Пояснення для цього ключового слова + 5 правил для ключових слів для початківців JS

thisКлючове слово JavaScript - це один із найскладніших аспектів мови, який можна зрозуміти. Але це критично важливо для написання вдосконаленого коду JavaScript.

У JavaScript thisключове слово дозволяє нам:

  • Повторне використання функцій у різних контекстах та
  • Визначте, на якому об’єкті зосередитись, коли викликається метод.

Коли справа доходить до this, важливим питанням, яке потрібно задати, є те, де використовується функція. Тому що ми не знаємо, що є в thisключовому слові, доки функція не буде викликана.

Використання thisможна поділити на п’ять різних bindingаспектів. У цій статті ми дізнаємось про всі п’ять аспектів на прикладах.

По-перше, що таке прив'язка?

В JavaScript Lexical Environmentце код, де ваш код написаний фізично. У наведеному нижче прикладі ім'я змінної знаходиться lexicallyвсередині функції sayName().

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

Посилання Execution Contextстосується коду, який наразі запущений, і всього іншого, що допомагає його запустити. Доступних лексичних середовищ може бути багато, але запущене в даний час управляється контекстом виконання .

Кожен з контекстів виконання містить Environment Record. Bindingу JavaScript означає запис ідентифікатора (змінної та назви функції) у конкретному Записі навколишнього середовища.

Примітка: Bindingдопомагає пов’язати ідентифікатор (ім’я змінної та функції) із thisключовим словом для execution context.

Не хвилюйтеся, якщо вам зараз це важко зрозуміти. Ви будете краще розуміти, як ми продовжуватимемо.

Правило №1: Як працює неявна прив'язка JavaScript

Неявне прив'язування охоплює більшість випадків використання thisключового слова.

При неявному прив'язуванні вам потрібно перевірити, що знаходиться ліворуч від оператора крапки (.), Що примикає до функції під час виклику. Це визначає, до чого thisобов’язково.

Давайте розглянемо приклад, щоб краще його зрозуміти.

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

Тут thisприв'язується до об'єкта користувача. Ми знаємо це, оскільки ліворуч від оператора крапка (.), Що примикає до функції getName(), ми бачимо userоб’єкт. Так this.nameзбирається реєструвати Тапас у консолі.

Побачимо ще один приклад, щоб краще зрозуміти це поняття:

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

У цьому прикладі ми маємо два об’єкти tomі jerry. Ми прикрасили (покращили) ці об'єкти, приєднавши метод з назвою logName().

Зверніть увагу, що коли ми викликаємо tom.logName(), tomоб’єкт знаходиться ліворуч від оператора крапка (.), Що примикає до функції logName(). Так thisприв'язується до tomоб'єкта, і він реєструє значення tom ( this.nameтут дорівнює tom). Те саме стосується jerry.logName()і виклику.

Правило №2: Як працює явне прив’язування JavaScript

Ми побачили, що JavaScript створює середовище для виконання коду, який ми пишемо. Він піклується про створення пам’яті для змінних, функцій, об’єктів тощо на етапі створення . Нарешті, він виконує код на етапі виконання . Це особливе середовище називається Execution Context.

Таких середовищ (контекстів виконання) у програмі JavaScript може бути багато. Кожен контекст виконання діє незалежно від інших.

Але часом ми можемо захотіти використовувати речі з одного контексту виконання в іншому. Ось тут і з’являється явне прив’язування.

У явному прив'язуванні ми можемо викликати функцію з об'єктом, коли функція знаходиться поза контекстом виконання об'єкта.

Є три дуже спеціальні методи call(), apply()і bind()які допомагають нам досягти явного зв'язування.

Як працює call()метод JavaScript

За допомогою call()методу контекст, з яким потрібно викликати функцію, буде передано як параметр до call(). Давайте подивимося, як це працює, на прикладі:

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

Тут call()метод викликається для функції, що називається getName(). getName()Функція просто реєструє this.name. Але що thisтут? Це визначається тим, що було передано call()методу.

Тут thisбуде прив’язано до об’єкта користувача, оскільки ми передали користувача як параметр call()методу. Тому this.nameслід реєструвати значення властивості name об'єкта користувача, тобто Tapas .

У наведеному вище прикладі ми передали лише один аргумент call(). Але ми також можемо передавати кілька аргументів call(), наприклад:

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

Тут ми передали кілька аргументів call()методу. Першим аргументом повинен бути контекст об'єкта, з яким функція повинна викликатися. Інші параметри можуть бути просто значеннями для використання.

Тут я передаю функції плавання та ведення блогу як два параметри getName().

Ви помітили тут больовий момент? У випадку call(), аргументи потрібно передавати по одному - що не є розумним способом робити щось! Ось де наш наступний метод apply(), входить у картину.

Як працює apply()метод JavaScript

This hectic way of passing arguments to the call() method can be solved by another alternate method called apply(). It is exactly the same as call() but allows you to pass the arguments more conveniently. Have a look:

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

Here we are able to pass an array of arguments, which is much more convenient than passing them one by one.

Tip: When you only have one value argument or no value arguments to pass, use call(). When you have multiple value arguments to pass, use apply().

How The JavaScript bind() Method Works

The bind() method is similar to the call() method but with one difference. Unlike the call() method of calling the function directly, bind() returns a brand new function and we can invoke that instead.

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.