--- title: Function.prototype.apply() slug: Web/JavaScript/Reference/Global_Objects/Function/apply tags: - Function - JavaScript - Method - Reference - Référence(2) translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply ---
Метод apply()
вызывает функцию с указанным значением this
и аргументами, предоставленными в виде массива (либо массивоподобного объекта).
Примечание: хотя синтаксис этой функции практически полностью идентичен функции {{jsxref("Function.prototype.call()", "call()")}}, фундаментальное различие между ними заключается в том, что функция call()
принимает список аргументов, в то время как функция apply()
принимает единичный массив аргументов.
fun.apply(thisArg, [argsArray])
thisArg
this
, предоставляемое для вызова функции fun
. Обратите внимание, что this
может не быть реальным значением, видимым этим методом: если метод является функцией в {{jsxref("Functions_and_function_scope/Strict_mode", "нестрогом режиме", "", 1)}}, значения {{jsxref("Global_Objects/null", "null")}} и {{jsxref("Global_Objects/undefined", "undefined")}} будут заменены глобальным объектом, а примитивные значения будут упакованы в объекты.argsArray
fun
должна быть вызвана, либо {{jsxref("Global_Objects/null", "null")}} или {{jsxref("Global_Objects/undefined", "undefined")}}, если в функцию не надо передавать аргументы. Начиная с ECMAScript 5 эти аргументы могут быть обобщёнными массивоподобными объектами, а не только массивом. Смотрите ниже информацию по {{anch("Browser_compatibility", "совместимости с браузерами")}}.Вы можете присваивать различные объекты this
при вызове существующей функции. this
ссылается на текущий объект, вызывающий объект. С помощью apply()
вы можете написать метод один раз, а затем наследовать его в других объектах без необходимости переписывать метод для каждого нового объекта.
Метод apply
очень похож на метод {{jsxref("Function.prototype.call()", "call()")}}, за исключением поддерживаемого типа аргументов. Вы можете использовать массив аргументов вместо набора именованных параметров. Вместе с apply
вы можете использовать литерал массива, например, fun.apply(this, ['есть', 'бананы'])
, либо объект {{jsxref("Global_Objects/Array", "Array")}}, например, fun.apply(this, new Array('есть', 'бананы'))
.
Также вы можете использовать в качестве параметра argsArray
псевдомассив {{jsxref("Functions_and_function_scope/arguments", "arguments")}}. arguments
является локальной переменной функции. Он может использоваться для всех неопределённых аргументов вызываемого объекта. Таким образом, вы не обязаны знать, сколько и какие аргументы требует вызываемый объект при использовании метода apply()
. Вы можете использовать псевдомассив arguments
для передачи всех аргументов в вызываемый объект. Вызываемый объект самостоятельно разберётся с обработкой аргументов.
Начиная с 5-го издания ECMAScript, вы также можете использовать любой вид массивоподобного объекта, что на практике означает, что он должен иметь свойство length
и целочисленные свойства в диапазоне (0...length)
. В качестве примера, теперь вы можете использовать {{domxref("NodeList")}} или свой собственный объект вида { 'length': 2, '0': 'есть', '1': 'бананы' }
.
{{note("Большинство браузеров, включая Chrome 14 и Internet Explorer 9, всё ещё не принимают массивоподобные объекты и будут выбрасывать исключение.")}}
apply()
для связи конструкторов объекта в цепочкуВы можете использовать метод apply()
для объединения в цепочку {{jsxref("Operators/new", "конструкторов", "", 1)}} объекта, как в Java. В следующем примере мы создадим в объекте {{jsxref("Global_Objects/Function", "Function")}} глобальный метод construct()
, который позволит нам использовать массивоподобные объекты с конструктором вместо списка аргументов.
Function.prototype.construct = function (aArgs) { var oNew = Object.create(this.prototype); this.apply(oNew, aArgs); return oNew; };
Примечание: метод {{jsxref("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()
не будет работать с некоторыми родными конструкторами (вроде конструктора {{jsxref("Global_Objects/Date", "Date")}}, к примеру). В этих случаях вы можете использовать метод {{jsxref("Function.prototype.bind()")}} (например, представьте, что вы имеете следующий массив, который можно использовать с конструктором {{jsxref("Global_Objects/Date", "Date")}}: [2012, 11, 4]
; в этом случае вы напишите что-то вроде: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()
— так или иначе, это не самый изящный способ и, вероятно, его не стоит использовать в рабочем окружении).
apply()
и встроенных функцийУмное использование метода apply()
позволяет вам использовать встроенные функции для некоторых задач, для которых в противном случае пришлось бы писать цикл по массиву значений. В качестве примера давайте используем {{jsxref("Math.max()")}}/{{jsxref("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]...
, например, тех что используются в Инспекторе инструментов разработчика).
{{Compat}}