Js bind call apply чем отличаются

от admin

Javascript — методы call, apply, bind

Метод call и apply достаточно древние — они оба из стандарта ES3. Суть создания и работы методов — заставить некоторую произвольную функцию работать на каком-то объекте. Точнее — использовать контекст этого объекта.

Чтобы было понятнее, начнем с примера. Есть функция, которая работает таким образом:

Что будет, если вызвать эту функцию таким образом?

Сложный вопрос, так как мы видим, что в теле функции используется ключевое слово this. Это — ссылка на текущий объект и на свойство name этого объекта. Что это за объект? Неизвестно. Все будет зависеть от того, где будет вызвана функция getName() на исполнение. Допустим, если вызвать функцию в консоли браузера, то парсер обратиться к глобальному объекту window и попробует найти у него свойство name. В итоге мы получим undefined, так как вряд ли у объекта window есть свойство name.

При помощи метода call можно “привязать” функцию getName() к любому объекту. Другими словами — привязать контекст функции getName() к контексту объекта. Как?

Допустим, у нас есть объект:

Что будет происходить здесь? В этом случае ключевое слово this (в теле функции getName) будет указывать на объект user1, у которого есть свойство name. Как результат — в константе result1 будет находиться значение Ivan.

Если создадим еще один объект:

И на нем вызовем функцию getName():

Что будет? В этом случае функция getName будет ссылаться уже на объект user2! И в константе result2 уже будет значение свойства name объекта user2 — Joshua.

call — более сложный вариант

Рассмотрим более сложный случай — когда функция принимает аргумент(ы). Допустим, такая функция,

И есть два объекта:

Вызовем функцию promote() на каждом из объектов:

Что здесь произойдет? При каждом вызове функции promote() у нее будет разный контекст выполнения — объект junior, middle или senior. И обращаться функция promote() будет каждый раз к свойствам разных объектов — junior, middle или senior. Соответственно, результат тоже будет разным:

Метод apply

Метод apply очень похож на метод call, за одним исключением. Аргументы метод apply принимает в виде массива, а не в виде списка, как метод call.

Проиллюстрируем пример — переделаем вызов функции promote() при помощи метода apply:

Видим, что аргументы передаются в виде массива, но результат будет тот же. Как часто упоминается в различных туториалах, это сделано для того, чтобы передать неограниченное и заранее неизвестное количество аргументов.

Метод bind

Этот метод похож на предыдущие два — call и apply. Однако, у него есть два отличия — этот метод появился в стандарте ES5; и второе отличие — этот метод позволяет выполнить отложенный вызов функции.

То есть — метод call или apply вызываются на исполнение сразу, и результат их работы мы получаем сразу. С методом bind немного иначе:

Что мы сдесь сделали? Мы вызвали функции promote() и передали ей контекст выполнения; результат — экземпляр функции promote() с уже встроенным контекстом выполнения; экземпляр помещен в константу resultAA, resultBB или resultCC. Другими словами — это готовые функции с контекстом.

Осталось вызвать любую из них и передать ей аргументы, которые она ожидает:

Видим — мы получили отложенный вызов каждой из функций.

Красивая функция trackBy

Пример красивой функции trackBy для Angular. Функция понравилась своей лаконичностью:<% highlight typescript %>public trackByNumber = (_. … Continue reading

Применение методов Bind(), Call(), and Apply() в JavaScript

Традиционно в JavaScript предоставляются объекты, обладающие собственными свойствами и методами. Например, object1 не может воспользоваться методами object2 и наоборот.

Однако есть способ обойти это ограничение.

Вы можете задействовать методы call() , apply() и bind() для привязки функции к объекту и ее вызова, как если бы она принадлежала этому объекту.

Рассмотрим поочередно данные методы и приведем с ними примеры.

Метод Call() в JavaScript

Метод call() вызывает функцию с заданным контекстом. Иначе говоря, вы привязываете функцию к объекту, как если бы она ему принадлежала.

Пример

Создадим объект obj и функцию add() для сложения одного числа с другим:

На данном этапе с add() возникает проблема. Она пытается вернуть this.num вкупе с каким-то значением. Но в функции отсутствует свойство num . Следовательно, вызвать this.num не удается.

Но, как вы могли заметить, у объекта obj есть свойство num . А что если бы у нас была возможность вызвать функцию add() для объекта, как если бы она ему принадлежала?

И такая возможность действительно есть. Для этого с помощью метода call() мигом привязываем функцию add() к объекту obj :

  • Теперь функция add() получает свой this из obj , к которому она привязана.
  • При вызове функции add() this.num ссылается на num объекта obj .
  • В результате вызов возвращает 5 , поскольку 2 + 3 = 5 .

Call() с несколькими аргументами

Возможен вариант использования call() с функциями, принимающими несколько аргументов.

Метод Apply() в JavaScript

Метод apply() аналогичен call() . Отличие лишь в том, что call() принимает список аргументов, а apply() — массив.

Метод Bind() в JavaScript

В предыдущих разделах мы выяснили суть методов call() и apply() : при вызове они моментально выполняют функцию и возвращают значение.

Принцип действия метода bind() напоминает call() и apply() , но в отличие от них он возвращает функцию, выполнение которой может быть отложено.

Скорректируем предыдущий пример, применив bind() :

Итак, вызов add.bind(obj, 3, 5) возвращает функцию. В этом случае вы присваиваете ее константе func и затем выполняете.

Здесь вызов func() означает вызов функции add() для объекта obj с аргументами 3, 5 .

Думаю, принципы работы методов call() , apply() и bind() понятны. Обобщим использование каждого из них с тем же самым объектом и привязанной к нему функцией, рассмотренными ранее.

Применение Call() в JavaScript

Настало время посмотреть, как работает метод call() в реальной жизни.

Call() для создания цепочек конструкторов объектов

Например, создаем объект Item . Конструктор Item определяется посредством name и price .

Теперь переходим к созданию объектов Car и Fruit , которые являются Items . Но на этот раз их инициализацию проведем не вышеописанным способом, а воспользовавшись объектом Item . Для этого понадобится метод call() :

Call() для вызова анонимной функции

Создадим анонимную функцию и посредством call() вызовем ее для каждого объекта массива

Анонимная функция добавляет функцию displayInfo() для каждого объекта массива, что позволяет вывести информацию о занимаемой позиции каждого человека в очереди:

Call() для выполнения функции с объектом

С одним таким примером мы уже познакомились при определении call() .

Речь идет о привязывании функции к объекту посредством метода call() , благодаря чему вы ее вызываете, как если бы она принадлежала объекту:

Применение Apply() в JavaScript

Apply() для добавления одного массива к другому

Для добавления элементов в массив потребуется метод push() .

При передаче массива в метод push() он добавляет его целиком как один элемент — в итоге вы получаете массив в массиве. Здесь можно использовать concat() , однако он создает новый массив.

Читать:
Getstdhandle c что это

Если нужно добавить массив целиком в уже существующий, задействуем apply() .

Apply() для создания цепочки конструкторов объектов

По аналогии с call() можно создавать цепочки конструкторов объектов с помощью apply() . На этот раз передаем массив с информацией в конструктор для инициализации объекта.

Применение Bind() в JavaScript

Bind() для создания связанной функции

Посредством bind() можно создать функцию, привязанную к объекту. При этом не имеет значения, где и как происходит ее вызов. Главное, что она вызывается вместе с объектом, с которым она связана.

Рассмотренный ранее пример иллюстрирует как раз этот случай.

Bind() для обеспечения работы SetTimeout

В этом фрагменте кода кроется проблема:

Вместо имени “John” он выдает undefined .

Выясним, в чем дело. Для этого перепишем последнюю строку по-другому:

Когда window вызывает свой метод setTimeout() , то объект this является объектом window . Следовательно, когда setTimeout() вызывает func , которая ссылается на person.getName() , он не располагает информацией об имени person . Для решения этой задачи привяжем функцию к объекту person с помощью метода bind() . В этом случае не имеет значения, где происходит вызов функции, — у нее всегда есть доступ к name объекта person .

Данный прием работает по следующим причинам:

  • Метод person.getName присваивается функции func , привязанной к к объекту person .
  • Теперь у func есть свой this , указывающий на объект person . При передаче связанной функции в setTimeout() func по-прежнему знает, как получить name объекта person .

Заключение

В JavaScript для привязки функции к объекту можно задействовать методы call() , apply() и bind() . В этом случае функция вызывается для объекта, как если бы она ему принадлежала.

  • Методы call() и apply() схожи в применении. Они оба сразу же выполняют связанную функцию для объекта.
  • В отличие от них метод bind() создает и возвращает связанную функцию, выполнение которой можно отложить.

Обобщим использование этих методов в следующем примере:

Благодарю за внимание! Надеюсь, информация была полезной. Успехов в программировании!

Как работают this, call, apply и bind в Java Script: разбираемся на примерах

Привет, Хабр! Эту статью написал Тарас Голомозый, fullstack web-разработчик и преподаватель в школе программирования Elbrus Bootcamp. В своей практике он часто сталкивается с кейсами выпускников, которых на собеседовании просят рассказать о роли ключевого слова this в JavaScript. Простого определения про ссылку на контекст часто оказывается недостаточно, требуется более глубокое погружение в тему. В этой статье он на нескольких примерах разбирает, в каких ситуациях может пригодиться это ключевое слово и как используется call, apply и bind.

В общем смысле this — это ссылка на определенный контекст внутри объекта. Рассмотрим, что это означает, на примере.

Создадим объект car с набором свойств: моделью и годом выпуска автомобиля.

Для того, чтобы обратиться к объекту извне, достаточно выбрать имя переменной и через точку выбрать любое свойство: например, model .

В консоли мы увидим модель автомобиля: Toyota.

Обратиться к объекту изнутри сложнее: находясь внутри фигурных скобок, мы не знаем, куда будет записан объект и будет ли записан вообще. Попробуем сделать это, создав внутри объекта функцию showModel . Ее единственная задача — показывать модель автомобиля:

Чтобы из этой функции получить доступ к model , пишем this.model . Благодаря ключевому слову this можно получить доступ к любому свойству объекта, находясь внутри него.

Теперь из объекта car можно вызвать showModel — метод покажет модель автомобиля, Toyota.

Допустим, у нас есть еще один автомобиль. Создадим новый объект и назовем его anotherCar . У этого объекта будут те же свойства: model и year .

Если скопировать функцию showModel с this внутрь нового объекта, то при вызове anotherCar.showModel , то в консоли мы увидим модель той машины, внутри которой вызывается этот метод. В данном случае — Benz.

Исходя из этих примеров, можно сказать, что this — это ссылка на объект, внутри которого находится это ключевое слово.

Важно отметить, что функции бывают обычными (как в этом примере) и стрелочными. Если в этом примере заменить функцию на стрелочную, в консоли мы увидим undefined. Дело в том, что стрелочные функции не имеют своего this.

Call, apply и bind

Что делать, если у второго автомобиля нет метода, который показывает его модель? Можем ли мы использовать функцию с вызовом модели первого автомобиля? Да, для этого в JavaScript есть специальные ключевые слова: call, apply и bind.

Начнем с call. Вызываем из первой машины метод car.showModel , используя call. В качестве аргумента ключевого слова указываем название объекта, в который записан второй автомобиль, anotherCar . В консоли мы увидим Benz.

То же самое можно сделать с помощью метода apply, просто меняя ключевое слово: car.showModel.apply(anotherCar); . Результат будет таким же: в консоли мы увидим Benz.

Возникает вопрос — чем call отличается от apply? Разница между ними в формате передачи параметров. Рассмотрим пример: функция showModel , кроме вывода модели автомобиля, может принимать еще какие-то параметры: например, цвет автомобиля и тип двигателя.

Используя apply, новые параметры можно передать в виде массива: например, автомобиль будет красным и с бензиновым двигателем:

В консоли мы увидим, что это красный дизельный Benz.

Call позволяет передать те же параметры не в виде массива, а простым перечислением: // car.showModel.call(anotherCar, ‘green’, ‘gas’) .

Третий метод, bind, позволяет создать новую функцию и записать ее в переменную. Выглядеть это будет так:

Функция modelShower вызывает метод showModel, а bind привязывает к нему контекст другого автомобиля — в нашем случае это anotherCar.Таким образом, в переменной modelShower появилась функция, способная показывать контекст anotherCar так, будто она написана внутри самого anotherCar.

Передадим в функцию цвет и параметры двигателя:

В выводе мы, как и ожидалось, получим черный дизельный Benz.

Заключение

Рады, если теперь вам удалось разобраться, что такое this в JavaScript, в чем разница между call и apply и для чего нужен bind. Если у вас появились вопросы или уточнения, пишите их в комментариях!

bind, call, apply в чём разница?

Собственно, сабж. Есть информация на английском, но хотелось бы осветить это и для тех, кто английский не знает.

ashalbulk's user avatar

Информация на русском есть, и очень много.

call — вызов функции с подменой контекста — this внутри функции. Пример:

apply — вызов функции с переменным количеством аргументов и с подменой контекста. Пример:

bind — создаёт «обёртку» над функцией, которая подменяет контекст этой функции. Поведение похоже на call и apply , но, в отличие от них, bind не вызывает функцию, а лишь возвращает «обёртку», которую можно вызвать позже. Пример:

Также bind умеет подменять не только контекст, но и аргументы функции, осуществляя каррирование:

Похожие статьи