JavaScript — невероятно гибкий язык, предлагающий множество способов управления контекстом функции. Три из этих методов: bind
, call
и apply
. Поначалу они могут показаться пугающими, но как только вы поймете их функцию и использование, вы обнаружите, что они являются мощными инструментами в вашем арсенале кодирования. В этой статье рассматривается, что делают эти методы, как их использовать и как создавать собственные версии. Мы также дадим несколько заданий, которые помогут закрепить ваше понимание.
Привязать, позвонить и подать заявку: что это такое?
Каждая функция в JavaScript имеет три метода: bind
, call
и apply
. Эти методы позволяют вам установить значение this
в функции, которое определяет контекст, в котором выполняется функция.
bind
: возвращает новую функцию, позволяющую передать массивthis
и любое количество аргументов. Аргументthis
используется в качестве контекста в функции.call
: вызывает функцию с заданным значениемthis
и аргументами, предоставленными индивидуально.apply
: Аналогиченcall
, но принимает массив аргументов вместо отдельных.
Связать в действии
bind
создает новую функцию с указанным значением this
, что позволяет вам управлять контекстом, в котором выполняется функция.
let obj = { name: 'John', }; function greet() { console.log(`Hello, my name is ${this.name}`); } let boundGreet = greet.bind(obj); boundGreet(); // "Hello, my name is John"
В данном случае boundGreet
— это новая функция с тем же телом, что и у greet
, но this
всегда связана с obj
.
Звоните и оставляйте заявку в действии
Методы call
и apply
похожи на bind
, но с одним существенным отличием: вместо создания новой функции они немедленно вызывают функцию с указанным значением this
.
let obj = { name: 'John', }; function greet(greeting, punctuation) { console.log(`${greeting}, my name is ${this.name}${punctuation}`); } greet.call(obj, 'Hello', '!'); // "Hello, my name is John!" greet.apply(obj, ['Hello', '!']); // "Hello, my name is John!"
И в call
, и в apply
this
устанавливается на obj
. Разница заключается в том, как передаются дополнительные аргументы: call
принимает список аргументов, а apply
принимает один массив аргументов.
Создайте свою собственную привязку, позвоните и подайте заявку
Вы также можете создавать свои собственные версии bind
, call
и apply
, используя прототипную природу JavaScript.
Вы правы, мои извинения. Если вы хотите избежать использования .apply
, .call
или .bind
в своей пользовательской реализации, все становится немного сложнее. Вот как вы можете это сделать:
Function.prototype.myBind = function(context) { var func = this; return function(...args) { var contextClone = Object.create(context); contextClone.func = func; return contextClone.func(...args); }; }; Function.prototype.myCall = function(context, ...args) { var contextClone = Object.create(context); contextClone.func = this; return contextClone.func(...args); }; Function.prototype.myApply = function(context, args) { var contextClone = Object.create(context); contextClone.func = this; return contextClone.func(...args); };
Каждый из этих методов работает, манипулируя контекстом функции и затем вызывая функцию с указанными аргументами.
Давайте поместим вышеуказанные функции для тестирования:
const name = 'Tom'; const obj = { name: 'Jerry', }; function greet(greeting, punctuation) { console.log(`${greeting}, ${this.name}${punctuation}`); } const boundGreet = greet.myBind(obj); boundGreet('Hello', '!'); // Should log: "Hello, Jerry!" greet.myCall(obj, 'Hi', '.'); // Should log: "Hi, Jerry." greet.myApply(obj, ['Hey', '!']); // Should log: "Hey, Jerry!"
Задания для закрепления вашего понимания
Задача 1. Изменение контекста с помощью Bind
Создайте объект person
с помощью методов name
и introduce
. Затем создайте еще один объект person2
, используя только файл name
. Используйте bind
, чтобы создать новую функцию, в которой person2
может представиться, используя метод introduce
из person1
.
let person1 = { name: 'John', introduce: function() { console.log(`Hello, my name is ${this.name}`); } }; let person2 = { name: 'Jane' }; let introduceJane = person1.introduce.bind(person2); introduceJane(); // "Hello, my name is Jane"
Задача 2. Вызов функций с помощью Call и Apply
Предположим, у вас есть объект car
с методом describe
. Создайте объект car2
с теми же свойствами, но без метода describe
. Используйте call
и apply
для вызова метода describe
из car1
для car2
.
let car1 = { make: 'Toyota', model: 'Camry', describe: function() { console.log(`This car is a ${this.make} ${this.model}`); } }; let car2 = { make: 'Honda', model: 'Civic' }; car1.describe.call(car2); // "This car is a Honda Civic" car1.describe.apply(car2); // "This car is a Honda Civic"
Задача 3. Реализация собственной функции Bind, Call и Apply
Используя определенные выше пользовательские функции myBind
, myCall
и myApply
, повторите действия, описанные в Задаче 1 и Задаче 2. Убедитесь, что они работают должным образом.
Понимание bind
, call
и apply
является ключом к освоению JavaScript, поскольку они дают вам больший контроль над контекстом, в котором выполняются ваши функции. Они могут сделать ваш код чище и гибче, а также открывают новые шаблоны и парадигмы кодирования. Так что найдите время, чтобы понять и попрактиковаться в их использовании, и вы быстро станете более опытным разработчиком JavaScript.