Використання `Call`, `Bind` та `Apply`: Поліфіли та як це працює

Розуміння методів call, apply та bind у JavaScript

Методи JavaScript call, apply та bind дозволяють явно встановлювати контекст this для функції. Ці методи є основою для розуміння динамічної поведінки this в JavaScript і часто зустрічаються на технічних співбесідах. Давайте розглянемо їх функціональність та те, як вони працюють внутрішньо.

1. call

Метод call дозволяє викликати функцію з вказаним значенням this. Першим аргументом є об'єкт, який буде використовуватись як this, а далі передаються аргументи, які будуть передані функції.

function greet(name) {
  console.log(`Hello, ${name}!`);
}

greet.call(null, 'Alice');  // Виведе: Hello, Alice!

У прикладі вище ми використовуємо call для виклику функції greet і передаємо аргумент 'Alice'.

2. apply

Метод apply є дуже схожим на call, але замість того, щоб передавати аргументи окремо, вони передаються як масив. Це зручно, коли кількість аргументів функції невідома або коли передача аргументів в масиві є більш зручною.

function greet(name, age) {
  console.log(`Hello, ${name}! You are ${age} years old.`);
}

greet.apply(null, ['Bob', 25]);  // Виведе: Hello, Bob! You are 25 years old.

Як бачите, ми передаємо аргументи через масив у методі apply.

3. bind

Метод bind створює нову функцію, де контекст this буде зафіксований на вказаному значенні. На відміну від call та apply, метод bind не викликає функцію негайно, а повертає нову функцію, яку можна викликати пізніше.

function greet(name) {
  console.log(`Hello, ${name}!`);
}

const greetAlice = greet.bind(null, 'Alice');
greetAlice();  // Виведе: Hello, Alice!

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

Висновок

Методи call, apply та bind є потужними інструментами для роботи з контекстом функцій в JavaScript. Вони дозволяють налаштовувати поведінку this для кожного конкретного виклику функції. Розуміння їх відмінностей та того, коли їх використовувати, є важливим аспектом для кожного розробника.

call

Мета:

Виконує функцію з вказаним контекстом this та аргументами, які передаються окремо.

Як це працює внутрішньо:

Function.prototype.myCall = function (context, ...args) {  
 context = context || globalThis; // За замовчуванням використовуємо глобальний об'єкт, якщо context = null або undefined  
 const uniqueKey = Symbol(); // Уникаємо конфліктів з іменами властивостей  
 context[uniqueKey] = this; // Тимчасово присвоюємо функцію контексту  
 const result = context[uniqueKey](...args); // Викликаємо функцію з аргументами, що передаються через spread  
 delete context[uniqueKey]; // Очищаємо тимчасову властивість  
 return result;  
};

Приклад використання:

function greet(greeting) {  
 console.log(`${greeting}, ${this.name}`);  
}  
const user = { name: "Alice" };  
greet.myCall(user, "Hello"); // Виведе: Hello, Alice

2.

apply

Мета:

Виконує функцію з вказаним контекстом this та аргументами, переданими у вигляді масиву.

Як це працює внутрішньо:

Function.prototype.myApply = function (context, args) {  
 context = context || globalThis;  
 const uniqueKey = Symbol();  
 context[uniqueKey] = this;  
 const result = args ? context[uniqueKey](...args) : context[uniqueKey]();  
 delete context[uniqueKey];  
 return result;  
};

Приклад використання:

function sum(a, b) {  
 return a + b;  
}  
console.log(sum.myApply(null, [1, 2])); // Виведе: 3

3. bind

Мета:

Створює нову функцію з вказаним контекстом this та необов'язковими заздалегідь переданими аргументами.

Функція не виконується негайно.

Як це працює внутрішньо:

Function.prototype.myBind = function (context, ...args) {  
 const fn = this; // Зберігаємо посилання на оригінальну функцію  
 return function (...innerArgs) {  
 return fn.apply(context, [...args, ...innerArgs]); // Комбінуємо аргументи  
 };  
};

Приклад використання:

function greet(greeting, punctuation) {  
 console.log(`${greeting}, ${this.name}${punctuation}`);  
}  
const user = { name: "Alice" };  
const boundGreet = greet.myBind(user, "Hello");  
boundGreet("!"); // Виведе: Hello, Alice!

Ключові відмінності між call, apply та bind

Виконання:

call: Негайне.

apply: Негайне.

bind: Затримане (повертає нову функцію).

Аргументи:

call: Передаються окремо.

apply: Передаються як масив.

bind: Передаються при зв'язуванні, додаткові аргументи — під час виклику.

Повернуте значення:

call: Результат викликаної функції.

apply: Результат викликаної функції.

bind: Нова зв'язана функція.

Інсайти для співбесід

Розуміння цих концепцій допоможе вам вирішити складніші питання на співбесідах, такі як:

  • Як динамічно визначається this у JavaScript.
  • Як bind дає можливість створювати замикання (closures) та працювати з прослуховувачами подій (Event Listeners).
  • Як call та apply спрощують використання методів з інших об'єктів.

Освоївши методи call, apply та bind, ви краще зрозумієте механізм this в JavaScript та його гнучкість у роботі з контекстом.
Це необхідні інструменти для написання чистого, модульного та багаторазового коду.

Перекладено з: Call, Bind and Apply : Pollyfills and How it works

Leave a Reply

Your email address will not be published. Required fields are marked *