Метод call и его особенности

157
15 октября 2018, 01:20

Метод вызывает функцию с новым значением this и переданными аргументами. Приведу немного кода и постараюсь объяснить, что происходит:

let slice = Array.prorotype.slice;
slice.call([1,2,3])

Мы скопировали ссылку на метод slice в переменную. Далее вызываем метод. Однако, простой вызов slice([1,2,3]) отработает некорректно, поскольку метод ожидает контекст извне. В этой связи мы, используя call, передаем нужный методу контекст и все работает.

Но я не очень хочу каждый раз передавать контекст. Поэтому делаю следующее:

slice = Function.prototype.call.bind(Array.prototype.slice);

Теперь можно вызывать метод без call:

slice([1,2,3]);

Все работает замечательно. Но проблема в том, что я не понимаю, как. Ведь метод slice принимает итерируемый объект в качестве this, судя по вызову slice.call([1,2,3]) или [1,2,3].slice(). Когда мы добавляем контекст методу call через bind таким способом slice = Function.prototype.call.bind(Array.prototype.slice) мы, по идее, возвращаем обертку в которой this = Array.prototype.slice. Ну и при следующем вызове slice([1,2,3]) я ожидаю, что выполняется такой код Function.prototype.call(Array.prototype.slice, [1,2,3]). Тогда, каким образом это работает? В документации написано, что Function.prototype.call принимает первым аргументом контекст, а следующими аргументы функции. Но как он знает о самой функции? Понятно, когда мы на какой-то функции вызывает call, типа slice.call. А когда мы делаем это через прототип? У меня одна догадка, что, когда мы вызываем функцию call через прототип Function.prototype.call, то первым аргументом передаем саму функцию, вторым контекст и дальше аргументы. Но я нигде не могу нагуглить информацию, которая подтверждала бы мои догадки. Подскажите, пожалуйста, как на самом деле работает этот вызов:

slice = Function.prototype.call.bind(Array.prototype.slice);
Answer 1

Смотрите. call - это метод, для которого this - это любая функция.

Когда вы пишите вот так:

slice.call([1,2,3])

То для метода slice контекстом (this) становится массив [1,2,3], а для метода call контекстом становится уже slice.

То же самое можно было бы написать и вот так:

call.call(slice, [1,2,3])

Когда вы пишите call.bind(slice) - вы фиксируете контекст для call, теперь это slice. А вот контекст slice не фиксируется, он по-прежнему ожидается в аргументе.

READ ALSO
Как создать очередь ajax запросов? [дубликат]

Как создать очередь ajax запросов? [дубликат]

На данный вопрос уже ответили:

191
Установить фон на canvas

Установить фон на canvas

Имеется изображение фона 50 на 50 px и холст размером 500 на 500, нужно изображениями фона заполнить весь холстКак это сделать?

166
JavaScript сравнение чисел в виде строки

JavaScript сравнение чисел в виде строки

Сижу и пишу условие на Vuejs

125