В чем разница между использованием call
и apply
вызовом функции?
var func = function() {
alert('hello!');
};
func.apply();
против func.call();
Есть ли различия в производительности между двумя вышеупомянутыми методами? Когда лучше использовать call
снова apply
и наоборот?
javascript
performance
function
dynamic
Джон Дафф
источник
источник
a
применении к массиву аргументов иc
вызове столбцов с аргументами.fn(...input)
где input - это массив. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Ответы:
Разница в том, что
apply
вы можете вызывать функциюarguments
как массив;call
требует, чтобы параметры были указаны явно. Полезный мнемонические является « для более rray и C для C OMMA.»См. Документацию MDN о том, как подать заявку и позвонить .
Псевдосинтаксис:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
Существует также, как и в ES6, возможность
spread
массива для использования сcall
функцией, вы можете увидеть совместимости здесь .Образец кода:
источник
[]
называется массивом ,{}
называется объектом .Array.prototype.slice.call(arguments)
или[].slice.call(arguments)
. Применение имеет смысл, если у вас есть аргументы в массиве, например, в функции, которая вызывает другую функцию с (почти) такими же параметрами. Рекомендация Используйте обычный вызов функции,funcname(arg1)
если он делает то, что вам нужно, и сохраните вызов и подайте заявку в тех особых случаях, когда они вам действительно нужны.call
иapply
принимает два параметра. Первый аргументapply' and
функции call` должен быть объектом-владельцем, а второй параметр будет соответственно параметром, разделенным массивом или запятой. Если вы передадитеnull
или вundefined
качестве первого аргумента, то в нестрогом режиме они будут заменены глобальным объектом, т.е.window
У К. Скотта Аллена хорошая статья по этому вопросу.
По сути, они отличаются тем, как они обрабатывают аргументы функции.
Так:
источник
call
но обязателенapply
Чтобы ответить на часть о том, когда использовать каждую функцию, используйте,
apply
если вы не знаете, сколько аргументов вы будете передавать, или если они уже находятся в массиве или массивоподобном объекте (например,arguments
объект для пересылки ваших собственных аргументов. Используйтеcall
иначе, так как нет необходимости заключать аргументы в массив.Когда я не передаю никаких аргументов (как ваш пример), я предпочитаю,
call
так как я вызываю функцию.apply
будет означать, что вы применяете функцию к (несуществующим) аргументам.Не должно быть никаких различий в производительности, за исключением, может быть, если вы используете
apply
и упаковываете аргументы в массив (например,f.apply(thisObject, [a, b, c])
вместоf.call(thisObject, a, b, c)
). Я не проверял это, поэтому могут быть различия, но это будет зависеть от браузера. Вероятно,call
это быстрее, если у вас еще нет аргументов в массиве, иapply
быстрее, если у вас есть.источник
Вот хорошая мнемоника. Pply использует A rrays и A сегда принимает один или два аргумента. Когда вы используете C все, что вам нужно, C Count количество аргументов.
источник
apply
требуется ни первый, ни второй параметры . Я не уверен, хотя, почему один будет вызыватьapply
илиcall
без параметра. Похоже, кто-то пытается выяснить, почему здесь stackoverflow.com/questions/15903782/…Хотя это старая тема, я просто хотел отметить, что .call немного быстрее, чем .apply. Я не могу сказать вам точно, почему.
См. JsPerf, http://jsperf.com/test-call-vs-apply/3
[
UPDATE!
]Дуглас Крокфорд кратко упоминает разницу между ними, что может помочь объяснить разницу в производительности ... http://youtu.be/ya4UHuXNygM?t=15m52s
Apply принимает массив аргументов, а Call принимает ноль или более отдельных параметров! Ах, ха!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
источник
Далее следует выдержка из книги «Закрытие: полное руководство» Майкла Болина . Это может выглядеть немного длинным, но оно насыщено глубоким пониманием. Из «Приложения Б. Часто неверно понимаемые концепции JavaScript»:
Что
this
относится к тому, когда вызывается функцияПри вызове функции формы
foo.bar.baz()
объектfoo.bar
называется получателем. Когда функция вызывается, это получатель, который используется в качестве значения дляthis
:Если нет явного получателя при вызове функции, тогда глобальный объект становится получателем. Как объясняется в «goog.global» на странице 47, окно - это глобальный объект, когда JavaScript выполняется в веб-браузере. Это приводит к неожиданному поведению:
Несмотря на то, что они ссылаются на одну
obj.addValues
иf
ту же функцию, при вызове они ведут себя по-разному, потому что значение получателя отличается при каждом вызове. По этой причине при вызове функции, которая ссылаетсяthis
, важно убедиться, что онаthis
будет иметь правильное значение при вызове. Чтобы было понятно, если быthis
не были ссылки в теле функции, то поведениеf(20)
иobj.addValues(20)
было бы таким же.Поскольку функции являются первоклассными объектами в JavaScript, они могут иметь свои собственные методы. Все функции имеют методы
call()
иapply()
которые дают возможность переопределить приемник (то есть объект , которыйthis
относится к) при вызове функции. Подписи метода следующие:Обратите внимание, что единственная разница между
call()
иapply()
заключается в том,call()
что параметры функции получают как отдельные аргументы, тогда как ониapply()
получают их как один массив:Следующие вызовы эквивалентны, как
f
иobj.addValues
относятся к той же функции:Тем не менее, поскольку ни один,
call()
ни другой неapply()
используют значение своего собственного получателя для замены аргумента получателя, когда он не указан, следующее не будет работать:Значение
this
никогда не может бытьnull
илиundefined
когда функция вызывается. Когдаnull
илиundefined
предоставляется как получатель дляcall()
илиapply()
, глобальный объект используется вместо значения для получателя. Следовательно, предыдущий код имеет тот же нежелательный побочный эффект, что и добавление свойства, названногоvalue
глобальным объектом.Может быть полезно думать о функции как о не имеющей знания о переменной, которой она назначена. Это помогает укрепить идею о том, что значение этого будет связано, когда функция вызывается, а не когда она определена.
Конец выписки.
источник
additionalValues
не упоминается внутриobj.addValues
телаvar f = obj.addValues;
становитсяvar f = obj.addValues.bind(obj)
и теперь f (20) будет работать без необходимости использовать вызов или применить каждый раз.Иногда полезно, чтобы один объект заимствовал функцию другого объекта, а это означает, что заимствующий объект просто выполняет одолженную функцию, как если бы она была его собственной.
Небольшой пример кода:
Эти методы очень полезны для придания объектам временной функциональности.
источник
console.log
посмотрите: что такое console.log и как его использовать?Еще один пример с Call, Apply и Bind. Разница между Call и Apply очевидна, но Bind работает так:
}
источник
Я хотел бы показать пример, где используется аргумент valueForThis:
** подробности: http://es5.github.io/#x15.4.4.7 *
источник
Call () принимает аргументы через запятую, например:
.call(scope, arg1, arg2, arg3)
и apply () принимает массив аргументов, например:
.apply(scope, [arg1, arg2, arg3])
Вот еще несколько примеров использования: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
источник
Из документов MDN на Function.prototype.apply () :
Из документов MDN на Function.prototype.call () :
Из Function.apply и Function.call в JavaScript :
Пример кода:
Смотрите также эту скрипку .
источник
Принципиальное отличие состоит в том, что
call()
принимает список аргументов , в то время какapply()
принимает один массив аргументов .источник
Вот небольшой пост, я написал об этом:
http://sizeableidea.com/call-versus-apply-javascript/
источник
Разница заключается в том,
call()
что аргументы функции принимаются отдельно, аapply()
аргументы функции - в массиве.источник
Мы можем дифференцировать вызов и применять методы, как показано ниже
CALL: функция с аргументом обеспечивает индивидуально. Если вы знаете аргументы для передачи или нет аргументов для передачи, вы можете использовать call.
ПРИМЕНИТЬ: вызвать функцию с аргументом, представленным в виде массива. Вы можете использовать apply, если вы не знаете, сколько аргументов будет передано функции.
Есть преимущество использования apply over call, нам не нужно изменять количество аргументов, только мы можем изменить передаваемый массив.
Там нет большой разницы в производительности. Но мы можем сказать, что вызов немного быстрее, чем сравнение для применения, потому что массив должен оцениваться в методе apply.
источник
Разница между этими методами заключается в том, как вы хотите передать параметры.
«A для массива и C для запятой» - удобная мнемоника.
источник
Вызов и применение обоих используются для принудительного вызова
this
значения при выполнении функции. Единственная разница в том, чтоcall
принимаетn+1
аргументы, где 1this
и'n' arguments
.apply
принимает только два аргумента, одинthis
из которых является массивом аргументов.Преимущество я вижу в
apply
более чем вcall
том , что мы можем легко передать вызов функции другой функции без особых усилий;Обратите внимание , как легко мы делегировали
hello
вsayHello
использованииapply
, но сcall
этим очень трудно достичь.источник
Несмотря на то,
call
иapply
achive то же самое, я думаю , что есть по крайней мере одно место , где вы не можете использовать ,call
но может использовать толькоapply
. Это когда вы хотите поддерживать наследование и хотите вызвать конструктор.Вот функция, позволяющая создавать классы, которая также поддерживает создание классов путем расширения других классов.
источник
Резюме:
Оба
call()
иapply()
являются методами, которые расположены наFunction.prototype
. Поэтому они доступны для каждого объекта функции через цепочку прототипов. Обаcall()
иapply()
могут выполнять функцию с указанным значениемthis
.Основное различие между
call()
иapply()
заключается в том, как вы должны передавать аргументы в него. В обоих случаях,call()
иapply()
вы передаете в качестве первого аргумента объект , который вы хотите быть значение , какthis
. Другие аргументы отличаются следующим образом:call()
вы должны поставить аргументы как обычно (начиная со второго аргумента)apply()
вами нужно передать массив аргументов.Пример:
Зачем мне нужно использовать эти функции?
this
Значение может быть сложно иногда в JavaScript. Значениеthis
определяется, когда функция выполняется, а не когда функция определена. Если наша функция зависит от правильнойthis
привязки, мы можем использовать этоcall()
иapply()
применять его. Например:источник
Основное отличие заключается в том, что с помощью вызова мы можем изменить область и передать аргументы как обычно, но применять позволяет вам вызывать его, используя аргументы в качестве массива (передавая их как массив). Но с точки зрения того, что они должны делать в вашем коде, они довольно похожи.
Итак, как видите, нет большой разницы, но все же есть случаи, когда мы предпочитаем использовать call () или apply (). Например, посмотрите на приведенный ниже код, который находит наименьшее и наибольшее число в массиве из MDN, используя метод apply:
Таким образом, главное отличие заключается в том, как мы передаем аргументы:
Call:
Применять:
источник
Позвольте мне добавить немного деталей к этому.
эти два вызова почти эквивалентны:
Там только небольшая разница:
Итак, эти звонки дополняют друг друга. Там, где мы ожидаем повторяемость ,
call
работает, где мы ожидаем, как массив ,apply
работает.А для объектов, которые являются итеративными и похожими на массивы , например реальный массив, мы технически могли бы использовать любой из них, но применение , вероятно, будет быстрее, потому что большинство движков JavaScript внутренне оптимизируют его лучше.
источник