[Medium] 📄 Привязка this
1. Что такое this в JavaScript?
Что такое
thisв JavaScript?
this — это ключевое слово в JavaScript, которое указывает на объект контекста выполнения функции.
Значение this зависит от того, как функция вызвана, а не от того, где она определена.
Правила привязки this
В JavaScript существует четыре правила привязки this (от высшего к ни зшему приоритету):
- Привязка new: функция вызвана с
new - Явная привязка:
call,applyилиbindявно устанавливаютthis - Неявная привязка: вызывается как метод объекта
- Привязка по умолчанию: поведение по умолчанию в других местах вызова
2. Объясните различие this в разных контекстах
Объясните, как ведёт себя
thisв разных контекстах.
1. this в глобальном контексте
console.log(this); // браузер: window, Node.js: global
function globalFunction() {
console.log(this); // не strict: window/global, strict: undefined
}
globalFunction();
'use strict';
function strictFunction() {
console.log(this); // undefined
}
strictFunction();
2. this в обычных функциях
Для обычных функций this зависит от места вызова:
function regularFunction() {
console.log(this);
}
// прямой вызов
regularFunction(); // window (не strict) или undefined (strict)
// вызов как метод
const obj = {
method: regularFunction,
};
obj.method(); // obj
// call/apply/bind
const customObj = { name: 'Custom' };
regularFunction.call(customObj); // customObj
3. this в стрелочных функциях
Стрелочные функции не имеют собственного this.
Они наследуют this из внешней лексической области.
const obj = {
name: 'Object',
// обычный метод
regularMethod: function () {
console.log('regularMethod this:', this); // obj
// внутренняя обычная функция: this меняется
function innerRegular() {
console.log('innerRegular this:', this); // window/undefined
}
innerRegular();
// внутренняя стрелочная функция: this наследуется
const innerArrow = () => {
console.log('innerArrow this:', this); // obj
};
innerArrow();
},
// стрелочная функция как свойство объекта
arrowMethod: () => {
console.log('arrowMethod this:', this); // window/global лексическая область
},
};
obj.regularMethod();
obj.arrowMethod();
4. this в методах объекта
const person = {
name: 'John',
age: 30,
// обычная функция: this -> person
greet: function () {
console.log(`Hello, I'm ${this.name}`); // "Hello, I'm John"
},
// сокращённый синтаксис ES6: this -> person
introduce() {
console.log(`I'm ${this.name}, ${this.age} years old`);
},
// стрелочная функция: this наследуется из внешней области
arrowGreet: () => {
console.log(`Hello, I'm ${this.name}`); // обычно undefined для name
},
};
person.greet();
person.introduce();
person.arrowGreet();
5. this в функциях-конструкторах
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function () {
console.log(`Hello, I'm ${this.name}`);
};
}
const john = new Person('John', 30);
john.greet();
console.log(john.name); // "John"
6. this в классах
class Person {
constructor(name) {
this.name = name;
}
// обычный метод: this -> экземпляр
greet() {
console.log(`Hello, I'm ${this.name}`);
}
// стрелочная функция в поле класса: this постоянно привязан к экземпляру
arrowGreet = () => {
console.log(`Hi, I'm ${this.name}`);
};
}
const john = new Person('John');
john.greet(); // "Hello, I'm John"
// извлечение метода теряет this
const greet = john.greet;
greet(); // ошибка в strict mode
// стрелочное поле сохраняет this
const arrowGreet = john.arrowGreet;
arrowGreet(); // "Hi, I'm John"
3. Задачи: что будет вы ведено?
Задачи: что выведет следующий код?
Задача 1: метод объекта vs стрелочная функция
const obj = {
name: 'Object',
regularFunc: function () {
console.log('A:', this.name);
},
arrowFunc: () => {
console.log('B:', this.name);
},
};
obj.regularFunc();
obj.arrowFunc();
Нажмите, чтобы увидеть ответ
// A: Object
// B: undefined
Объяснение:
regularFuncвызвана какobj.regularFunc(), поэтомуthisравенobjarrowFuncне имеет собственногоthis; наследует внешний/глобальный лексическийthis
Задача 2: передача функции как аргумента
const person = {
name: 'John',
greet: function () {
console.log(`Hello, ${this.name}`);
},
};
person.greet(); // 1
const greet = person.greet;
greet(); // 2
setTimeout(person.greet, 1000); // 3
Нажмите, чтобы увидеть ответ
// 1: "Hello, John"
// 2: "Hello, undefined" или ошибка в strict mode
// 3: "Hello, undefined" или ошибка в strict mode
Объяснение:
person.greet()-> неявная привязка,thisравенperson- Извлечённая функция ->
thisпотерян - Callback, переданный в
setTimeout->thisне равенperson
Задача 3: вложенные функции
const obj = {
name: 'Outer',
method: function () {
console.log('A:', this.name);
function inner() {
console.log('B:', this.name);
}
inner();
const arrow = () => {
console.log('C:', this.name);
};
arrow();
},
};
obj.method();
Нажмите, чтобы увидеть ответ
// A: Outer
// B: undefined
// C: Outer
Объяснение:
A:methodвызван отobjB:inner— обычный прямой вызовC: стрелочная функция наследуетthisвнешнегоmethod