This page was translated from English by the community.Learn more and join the MDN Web Docs community.
Function.prototype.apply()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since июль 2015 г..
Общие сведения
Методapply() вызывает функцию с указанным значениемthis и аргументами, предоставленными в виде массива (либомассивоподобного объекта).
Примечание:Хотя синтаксис этой функции практически полностью идентичен функцииcall(), фундаментальное различие между ними заключается в том, что функцияcall() принимает список аргументов, в то время как функцияapply() принимает единичный массив аргументов.
In this article
Синтаксис
fun.apply(thisArg, [argsArray])
Параметры
thisArgЗначение
this, предоставляемое для вызова функцииfun. Обратите внимание, чтоthisможет не быть реальным значением, видимым этим методом: если метод является функцией внестрогом режиме, значенияnullиundefinedбудут заменены глобальным объектом, а примитивные значения будут упакованы в объекты.argsArrayНеобязательныйМассивоподобный объект, определяющий аргументы, с которыми функция
funдолжна быть вызвана, либоnullилиundefined, если в функцию не надо передавать аргументы. Начиная с ECMAScript 5 эти аргументы могут быть обобщёнными массивоподобными объектами, а не только массивом. Смотрите ниже информацию посовместимости с браузерами.
Описание
Вы можете присваивать различные объектыthis при вызове существующей функции.this ссылается на текущий объект, вызывающий объект. С помощьюapply() вы можете написать метод один раз, а затем наследовать его в других объектах без необходимости переписывать метод для каждого нового объекта.
Методapply очень похож на методcall(), за исключением поддерживаемого типа аргументов. Вы можете использовать массив аргументов вместо набора именованных параметров. Вместе сapply вы можете использовать литерал массива, например,fun.apply(this, ['есть', 'бананы']), либо объектArray, например,fun.apply(this, new Array('есть', 'бананы')).
Также вы можете использовать в качестве параметраargsArray псевдомассивarguments.arguments является локальной переменной функции. Он может использоваться для всех неопределённых аргументов вызываемого объекта. Таким образом, вы не обязаны знать, сколько и какие аргументы требует вызываемый объект при использовании методаapply(). Вы можете использовать псевдомассивarguments для передачи всех аргументов в вызываемый объект. Вызываемый объект самостоятельно разберётся с обработкой аргументов.
Начиная с 5-го издания ECMAScript, вы также можете использовать любой вид массивоподобного объекта, что на практике означает, что он должен иметь свойствоlength и целочисленные свойства в диапазоне(0...length). В качестве примера, теперь вы можете использоватьNodeList или свой собственный объект вида{ 'length': 2, '0': 'есть', '1': 'бананы' }.
Примечание:Большинство браузеров, включая Chrome 14 и Internet Explorer 9, всё ещё не принимают массивоподобные объекты и будут выбрасывать исключение.
Примеры
>Пример: использованиеapply() для связи конструкторов объекта в цепочку
Вы можете использовать методapply() для объединения в цепочкуконструкторов объекта, как в Java. В следующем примере мы создадим в объектеFunction глобальный методconstruct(), который позволит нам использовать массивоподобные объекты с конструктором вместо списка аргументов.
Function.prototype.construct = function (aArgs) { var oNew = Object.create(this.prototype); this.apply(oNew, aArgs); return oNew;};Примечание:МетодObject.create(), использованный в этом примере, относительно новый. В качестве альтернативного способа можно рассмотреть возможность использования замыкания:
Function.prototype.construct = function (aArgs) { var fConstructor = this, fNewConstr = function () { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr();};Пример использования:
function MyConstructor() { for (var nProp = 0; nProp < arguments.length; nProp++) { this["property" + nProp] = arguments[nProp]; }}var myArray = [4, "Привет, мир!", false];var myInstance = MyConstructor.construct(myArray);alert(myInstance.property1); // выведет 'Привет, мир!'alert(myInstance instanceof MyConstructor); // выведет 'true'alert(myInstance.constructor); // выведет 'MyConstructor'Примечание:Этот неродной методFunction.construct() не будет работать с некоторыми родными конструкторами (вроде конструктораDate, к примеру). В этих случаях вы можете использовать методFunction.prototype.bind() (например, представьте, что вы имеете следующий массив, который можно использовать с конструкторомDate:[2012, 11, 4]; в этом случае вы напишите что-то вроде:new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))() — так или иначе, это не самый изящный способ и, вероятно, его не стоит использовать в рабочем окружении).
Пример: использованиеapply() и встроенных функций
Умное использование методаapply() позволяет вам использовать встроенные функции для некоторых задач, для которых в противном случае пришлось бы писать цикл по массиву значений. В качестве примера давайте используемMath.max()/Math.min() для нахождения максимального/минимального значения в массиве.
/* мин/макс числа в массиве */var numbers = [5, 6, 2, 3, 7];/* используем apply к Math.min/Math.max */var max = Math.max.apply( null, numbers,); /* Это эквивалентно Math.max(numbers[0], ...) или Math.max(5, 6, ...) */var min = Math.min.apply(null, numbers);/* сравним с простым алгоритмом с циклом */((max = -Infinity), (min = +Infinity));for (var i = 0; i < numbers.length; i++) { if (numbers[i] > max) { max = numbers[i]; } if (numbers[i] < min) { min = numbers[i]; }}Но будьте осторожны: при использовании методаapply() таким образом вы рискуете выйти за пределы ограничения на количество аргументов в движке JavaScript. Последствия применения функции с очень большим количеством аргументов (думается, больше десяти тысяч аргументов) различаются от движка к движку (JavaScriptCore имеет жёстко зашитоеограничение на количество аргументов в 65536), поскольку этот предел (на самом деле, это природа поведения любого чрезвычайно огромного стека) не определён. Некоторые движки будут выкидывать исключение. Хуже того, другие просто отбрасывают реально переданные функции аргументы сверх лимита. (Для иллюстрации последнего случая: если такой движок имеет ограничение в четыре элемента [реальное ограничение, конечно же, гораздо выше], это выглядело бы так, как если бы в примере выше в методapply() были переданы аргументы5, 6, 2, 3, а не весь массив.) Если ваш массив значений может вырасти до десятков тысяч, используйте смешанный подход: применяйте вашу функцию к порциям массива:
function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); min = Math.min(submin, min); } return min;}var min = minOfArray([5, 6, 2, 3, 7]);Пример: использованиеapply() в «monkey-патчинге»
Методapply() может быть лучшим вариантом для «monkey-патчинга» встроенных в Firefox функций, либо JS библиотек. Пусть у вас есть функцияsomeobject.foo(), вы можете изменить её таким немного хакерским способом:
var originalfoo = someobject.foo;someobject.foo = function () { // Делаем что-то до вызова функции console.log(arguments); // Вызываем функцию так, как будто бы она была вызвана обычным образом: originalfoo.apply(this, arguments); // Делаем что-то после вызова функции.};Этот метод особенно удобен, когда вам нужно отладить события, либо интерфейс с чем-то, что не имеет API, вроде различных событий.on([event]..., например, тех что используются вИнспекторе инструментов разработчика).
Спецификации
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-function.prototype.apply> |