09 серпня 2021

Ключове слово функції this

Тим, хто хоче вивчити JavaScript, в будь-якому випадку доведеться розібратися з ключовим словом this.
Ключове слово this використовується так часто в підручниках і в коді JavaScript, що вам потрібно в ньому розібратися.
Ключове слово функції this поводиться дещо інакше у JavaScript у порівнянні з іншими мовами. Воно також має певні відмінності між строгим та нестрогим режимами.
This - це ключове слово, яке використовується в JavaScript, яке має особливе значення, залежне від контексту в якому воно застосовується.
Ключове слово This відноситься до поточного об'єкту в методі або конструкторі.
Значення його змінюється в залежності від того, як викликається функція.

Є такі основні варіації, де воно може набувати різних значень:

  • this в глобальному контексті
  • this в конструкторі об’єкту
  • this в методі об’єкту
  • this в простій функції
  • this в слухачі подій
У більшості випадків, значення this визначається тим, як викликається функція (прив'язка під час виконання). Це і є тією причиною, по якій this викликає стільки плутанини у новачків. Отже контекст this змінюється в залежності від його використання.
This можна вважати динамічним ключовим словом.
Контекст завжди є значенням ключового слова this, яке посилається на об'єкт, «володіє» кодом, який виконується в поточний момент. Однак, той контекст, який має відношення до this, це не те ж саме, що контекст виконання.
Отже, коли ми користуємося ключовим словом this, ми, насправді, звертаємося з його допомогою до якогось об'єкту.
Воно не може бути переприсвоєне під час виконання, і може змінюватись кожен раз, коли викликається функція. ES5 запровадив метод bind() для присвоєння значення this у функції незалежно від того, як вона викликається, а ES2015 запровадив стрілкові функції, які не мають власної прив'язки this (вони зберігають значення this оточуючого лексичного контексту).

Синтаксис this

Значення

Властивість контексту виконання (глобального, функції чи eval), яка, у нестрогому режимі завжди посилається на об'єкт, а у строгому режимі може бути будь-яким значенням.

Глобальний контекст

У глобальному контексті виконання (поза межами будь-яких функцій) this посилається на глобальний об'єкт, як у строгому, так і у нестрогому режимі.
Коли this викликається поза будь-якою функцією, в глобальному контексті, в браузері за замовчуванням використовується об’єкт Window.
console.log (this); // об'єкт Window
Як правило, вам не потрібно використовувати this в глобальному контексті, оскільки його значення тут не важливе. Давайте перейдемо до наступного контексту.

Використання this всередині об'єкта

Коли this використовується всередині об'єкта, це ключове слово посилається на сам об'єкт. Розглянемо приклад. Припустимо, ви створили об'єкт dog з методами і звернулися в одному з його методів до this. Коли this використовується всередині цього методу, це ключове слово уособлює об'єкт dog.
var dog = {
name: 'Chester',
breed: 'beagle',
intro: function(){
console.log(this);
}
};
dog.intro();

// в консоль виводиться представлення об'єкта dog зі всіма його властивостями та методами
// {name: "Chester", breed: "beagle", intro: ƒ}
// breed:"beagle"
// intro:ƒ ()
// name:"Chester"
// __proto__:Object

Звернення до this з функції, яка була оголошена за межами об'єкта, а потім призначена в якості його методу

Розглянемо приклад з уже відомим нам об'єктом dog. В якості методу цього об'єкта можна призначити функцію chase, оголошену за його межами. Тут в об'єкті dog ніяких методів не було, до тих пір, поки ми не створили метод foo, яким призначена функція chase. Якщо тепер викликати метод dog.foo, то буде викликана функція chase. При цьому ключове слово this, до якого звертаються в цій функції, вказує на об'єкт dog. А функція chase, при спробі її виклику як самостійної функції, буде вести себе неправильно, так як при такому підході this буде вказувати на глобальний об'єкт, в якому немає тих властивостей, до яких ми, в цій функції, звертаємося через this.
var dog = {breed: 'Beagles',lovesToChase: 'rabbits'}; function chase() {console.log(this.breed + ' loves chasing ' + this.lovesToChase + '.');} dog.foo = chase; dog.foo(); // в консоль попаде Beagles loves chasing rabbits. chase(); //так цю функцію краще не викликати

Використання this в звичайних функціях.

Коли звичайна функція знаходиться в глобальному контексті, то ключове слово this, використане в ній, буде прив'язане до об'єкта window. Нижче наведено приклад, в якому функцію test можна розглядати у вигляді методу об'єкта window.
function test() {
console.log('hello world');
console.log(this);
}
test();
// hello world
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
Однак якщо функція виконується в строгому режимі, то в this буде записано undefined, так як в цьому режимі заборонені прив'язки за замовчуванням. Спробуйте запустити такий приклад в консолі браузера.
function test() {
'use strict';
return this;
}
console.log( test() );
//функція повертає undefined, а не об'єкт Window
Зверніть увагу:Ви завжди легко можете отримати глобальний об'єкт за допомогою глобальної властивості globalThis, незалежно від поточного контексту, у якому виконується ваш код.

Простий виклик.

Оскільки наступний код не є кодом у строгому режимі, і тому, що значення this не було присвоєне викликом, this за замовчуванням дорівнюватиме глобальному об'єкту, яким у переглядачі є window.
function f1() { return this; } // У переглядачі: f1() === window; // true // У Node: f1() === global; // true
Однак, у строгому режимі значення this не присвоюється при вході у контекст виконання, воно залишається undefined, як показано у наступному прикладі:
function f2() { 'use strict'; // дивіться строгий режим return this; } f2() === undefined; // true
У другому прикладі this має дорівнювати undefined, тому що функція f2 була викликана прямо, а не як метод чи властивість об'єкта (наприклад, window.f2()). Ця функціональність не була реалізована у деяких переглядачах, коли вони вперше почали підтримувати строгий режим. Як результат, вони неправильно повертали об'єкт window.

This і вкладені об'єкти

Застосування this у вкладених об'єктах може створити деяку плутанину. У подібних ситуаціях варто пам'ятати про те, що ключове слово this ставитися до того об'єкту, в методі якого воно використовується. Розглянемо приклад.
var obj1 = { hello: function() { console.log('Hello world'); return this; }, obj2: { breed: 'dog', speak: function(){ console.log('woof!'); return this; } } }; console.log(obj1); console.log(obj1.hello()); // виводить 'Hello world' і повертає obj1 console.log(obj1.obj2); console.log(obj1.obj2.speak()); // виводить 'woof!' і повертає obj2

Ключове слово new і this.

Ключове слово this знаходить застосування у функціях-конструкторах, використовуваних для створення об'єктів, так як воно дозволяє, універсальним чином, працювати з безліччю об'єктів, що створюються за допомогою такої функції. В JavaScript є і стандартні функції-конструктори, за допомогою яких, наприклад, можна створювати об'єкти типу Numberа бо String. Подібні функції, які визначаються програмістом самостійно, дозволяють йому створювати об'єкти, склад властивостей і методів яких задається їм самим. Як ви вже зрозуміли, мені подобаються собаки, тому опишемо функцію-конструктор для створення об'єктів типу Dog, що містять деякі властивості і методи.
function Dog(breed, name, friends){ this.breed = breed; this.name = name; this.friends = friends; this.intro = function() { console.log(`Hi, my name is ${this.name} and I’m a ${this.breed}`); return this; }; }
Коли функцію-конструктор викликають з використанням ключового слова new, this в ній вказує на новий об'єкт, який, за допомогою конструктора, постачають властивостями і методами.

Ось як можна працювати зі стандартними конструкторами JavaScript.

var str = new String('Hello world');

Рядки можна створювати так, але краще цього не робити, використовуючи підхід, застосований при оголошенні змінної str2 нижче. Одна з причин такої рекомендації полягає в тому, що в JavaScript рядки зручно створювати, користуючись строковими літералами, коли рядком вважається все, включене в подвійні або одинарні лапки. Те ж саме стосується і інших примітивних значень. Варто відзначити, що мені, на практиці, не зустрічалася ситуація, коли треба було б використовувати
var str2 = 'Hello world';
// коли рядок оголошена таким чином, система, все одно, дозволяє працювати з нею як з об'єктом
Тепер попрацюємо з щойно створеної функцією-конструктором Dog.
// Створимо новий екземпляр об'єкта типу Dog
var chester = new Dog('beagle', 'Chester', ['Gracie', 'Josey', 'Barkley']);
chester.intro(); // виводить Hi, my name is Chester and I'm a beagle
console.log(chester); // виводить Dog {breed: "beagle", name: "Chester", friends: Array(3), intro: ƒ}

Ось ще один приклад використання функцій-конструкторів.
var City = function(city, state) { this.city = city || "Phoenix"; this.state = state || "AZ"; this.sentence = function() { console.log(`I live in ${this.city}, ${this.state}.`); }; }; var phoenix = new City(); // використовуємо параметри за замовчуванням console.log(phoenix); // виводить в консоль рядкове представлення об'єкту phoenix.sentence(); // виводить I live in Phoenix, AZ. var spokane = new City('Spokane', 'WA'); console.log(spokane); // виводить сам об'єкт spokane.sentence(); // виводить I live in Spokane, WA.

Про важливість ключового слова new

При виконанні функції-конструктора з використанням ключового слова newключове слово thisвказує на новий об'єкт, який, після деякої роботи над ним, буде повернуто з цієї функції. Ключове слово thisв даній ситуації дуже важливо. Чому? Вся справа в тому, що з його допомогою можна, використовуючи єдину функцію-конструктор, створювати безліч однотипних об'єктів.
Це дозволяє нам масштабувати додаток і скорочувати дублювання коду. Для того щоб зрозуміти важливість цього механізму, подумайте про те, як влаштовані облікові записи в соціальних мережах. Кожна обліковий запис може являти собою екземпляр об'єкта, який створюється за допомогою функції-конструктора Friend. Кожен такий об'єкт можна заповнювати унікальними даними про користувача. Розглянемо наступний код.
// Функція-конструктор var Friend = function(name, password, interests, job){ this.fullName = name; this.password = password; this.interests = interests; this.job = job; }; function sayHello(){ // розкоментуйте наступний рядок, щоб дізнатися, на що вказує this // console.log(this); return `Hi, my name is ${this.fullName} and I'm a ${this.job}. Let's be friends!`; } // Ми можемо створити один або кілька примірників об'єкта типу Friend, //використовуючи ключове слово new var john = new Friend('John Smith', 'badpassword', ['hiking', 'biking', 'skiing'], 'teacher'); console.log(john); // Призначимо функцію ключу greeting об'єкта john john.greeting = sayHello; // Викличемо новий метод об'єкта console.log( john.greeting() ); // Пам'ятайте про те, що sayHello () не варто викликати як звичайну функцію console.log( sayHello() ) ;

Підсумки:
Насправді, особливості використання ключового слова this в JavaScript не обмежуються вищеописаними прикладами. Так, в низку цих прикладів можна було б включити використання функцій call, apply і bind. Так як матеріал цей розрахований на початківців і орієнтований на роз'яснення основ, ми їх тут не торкаємося. Однак якщо зараз у вас сформувалося початкове розуміння this, то і з цими методами ви цілком зможете розібратися. Головне - пам'ятайте про те, що якщо щось з першого разу зрозуміти не вдається, не припиняйте вчитися, практика, читайте матеріали по цікавить вас. В одному з них вам обов'язково попадеться щось таке (якась вдала фраза, наприклад), що допоможе зрозуміти те, що раніше зрозуміти не вдавалося.
Ключове слово this є одним з найважливіших ключових слів в JavaScript. Воно використовується в багатьох JavaScript-фреймворках, тому ви повинні знати, що воно робить.

0 Коментарів Підписатися на цей блог