Ответ 1
Ссылка на ECMAScript Language Specification 5.1 Edition (июнь 2011 г.):
15.3.4.3 Функция .prototype.apply(thisArg, argArray)
Когда метод apply
вызывается в функции func с аргументами thisArg и argArray, выполняются следующие шаги:
-
Если
IsCallable(func)
-false
, то бросьте исключениеTypeError
. -
Если
argArray
-null
илиundefined
, тогдаreturn
результат вызова внутреннего метода[[Call]]
func
, обеспечивающегоthisArg
как значениеthis
и пустой список аргументов. - Если
Type(argArray)
неObject
, то бросьте исключениеTypeError
. - Пусть
len
является результатом вызова внутреннего метода[[Get]]
argArray
с аргументом"length"
. - Пусть
n
beToUint32(len)
. - Пусть
argList
- пустойList
. - Пусть
index
будет 0. - Повторите, пока
index < n
- Пусть
indexName
beToString(index)
. - Пусть
nextArg
является результатом вызова внутреннего метода[[Get]]
argArray
сindexName
в качестве аргумента. - Добавить
nextArg
в качестве последнего элементаargList
. - Установите
index
вindex + 1
. - Возвращает результат вызова внутреннего метода
[[Call]]
func
, обеспечиваяthisArg
как значениеthis
иargList
в качестве списка Аргументы.
15.3.4.4 Function.prototype.call(thisArg [, arg1 [, arg2,...]])
Когда метод call
вызывается для объекта func с аргументом thisArg и необязательными аргументами arg1, arg2 и т.д., предпринимаются следующие шаги:
- Если
IsCallable(func)
-false
, то бросьте исключениеTypeError
. - Пусть
argList
- пустойList
. - Если этот метод вызывается с более чем одним аргументом, то в левом
в правильном порядке, начиная с
arg1
, добавьте каждый аргумент в качестве последнего элементargList
- Возвращает результат вызова внутреннего метода
[[Call]]
func
, обеспечиваяthisArg
как значениеthis
иargList
в качестве списка Аргументы.
Как мы видим, формат, в котором указан apply
, заметно тяжелее, и ему нужно сделать намного больше из-за необходимости изменить формат, в котором приведены аргументы и как они в конечном итоге необходимы.
Существует ряд проверок в apply
, которые не нужны в call
из-за разницы форматирования ввода.
Другим ключевым моментом является то, как аргументы зацикливаются (шаги 4-12 в apply
, подразумеваемые на шаге 3 из call
): вся настройка для цикла выполняется в apply
независимо от сколько там аргументов, в call
все это делается только при необходимости.
Кроме того, стоит отметить, что способ, которым реализован шаг 3 в call
, не указан, что поможет объяснить существенные различия в поведении браузера.
Итак, коротко повторим: call
быстрее, чем apply
, потому что входные параметры уже отформатированы по мере необходимости для внутреннего метода.
Обязательно прочитайте комментарии ниже для дальнейшего обсуждения.