--- title: Function.prototype.apply() slug: Web/JavaScript/Reference/Global_Objects/Function/apply tags: - Function - JavaScript - Довідка - Функція - метод translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply ---
Метод apply()
викликає функцію із заданим значенням this
та аргументами, переданими у вигляді масиву (або подібного до масиву об'єкта).
Заувага: Хоча синтаксис цієї функції є майже ідентичним до синтаксису {{jsxref("Function.call", "call()")}}, фундаментальна відмінність полягає в тому, що метод call()
приймає список аргументів, тоді як метод apply()
приймає єдиний масив аргументів.
Заувага: Коли першим аргументом є undefined або null, схожий результат можна отримати за допомогою оператора розпакування масивів.
{{EmbedInteractiveExample("pages/js/function-apply.html")}}
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
function.apply(thisArg, [argsArray])
thisArg
this
, передане для виклику у функцію function
. Зазначте, що this
може не бути фактичним значенням, яке бачить метод: якщо метод є функцією не у {{jsxref("Strict_mode", "строгому режимі", "", 1)}}, {{jsxref("null")}} та {{jsxref("undefined")}} будуть замінені глобальним об'єктом, а прості значення будуть запаковані. Цей аргумент є обов'язковим.argsArray
Результат виконання функції з вказаним значенням this
та аргументами.
Ви можете присвоїти інший об'єкт this
, коли викликаєте існуючу функцію. this
посилається на поточний об'єкт, з якого здійснюється виклик. З apply
ви можете написати метод один раз, а потім успадковувати його в іншому об'єкті, без необхідності переписувати метод для нового об'єкта.
Метод apply
дуже схожий на {{jsxref("Function.call", "call()")}}, за виключенням типу аргументів, які він підтримує. Ви використовуєте масив аргументів замість списку аргументів (параметрів). З методом apply
ви також можете використовувати літерал масиву, для прикладу, func.apply(this, ['їсти', 'банани'])
, або об'єкт {{jsxref("Array")}}, для прикладу, func.apply(this, new Array('їсти', 'банани'))
.
Ви також можете використати об'єкт {{jsxref("Functions/arguments", "arguments")}} як параметр argsArray
. arguments
- локальна змінна функції. Вона може використовуватись для всіх не заданих аргументів об'єкта, який викликається. Таким чином, вам не потрібно знати аргументи об'єкта, що викликається, коли ви використовуєте метод apply
. Ви можете скористатись об'єктом arguments,
щоб передати усі аргументи. Далі об'єкт, який викликається, відповідає за обробку аргументів.
З появою 5-ї версії ECMAScript, ви також можете використовувати будь-який подібний до масиву об'єкт, отже, на практиці це означає, що він має поле length
та цілі числа в якості параметрів у діапазоні (0...length-1)
. Як приклад, ви тепер можете використати {{domxref("NodeList")}} або власноруч написаний об'єкт виду { 'length': 2, '0': 'їсти', '1': 'банани' }
.
Чимало більш старих переглядачів, в тому числі Chrome <17 та Internet Explorer <9, не приймають подібні до масиву об'єкти і викидатимуть виняток.
apply
для додавання масиву до іншого масивуМи можемо використати метод push
, щоб додати елемент до масиву. І, оскільки push
приймає змінну кількість аргументів, ми також можемо додати кілька елементів за раз. Але, якщо ми передамо у push
масив, він додасть, власне, масив єдиним елементом, замість того, щоб додати окремі елементи, і ми отримаємо масив всередині масиву. Що, як ми не цього хотіли? Метод concat
має поведінку, яка нам потрібна в цьому випадку, але він не додає елементи у існуючий масив, а створює та повертає новий масив. Але ми хотіли додати елементи у існуючий масив... Що ж робити? Писати цикл? Звісно, ні.
На допомогу приходить apply
!
var array = ['a', 'b']; var elements = [0, 1, 2]; array.push.apply(array, elements); console.info(array); // ["a", "b", 0, 1, 2]
apply
та вбудовані функціїРозумне використання методу apply
дозволяє використовувати вбудовані функції для деяких задач, які в іншому випадку ймовірно були б написані циклічним обходом значень масиву. Як приклад, ми збираємося використати Math.max
/Math.min,
щоб знайти максимальне/мінімальне значення масиву.
// мінімальне/максимальне число в масиві var numbers = [5, 6, 2, 3, 7]; // використання Math.min/Math.max з apply 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
для ланцюгового виконання конструкторівВи можете використовувати apply
для ланцюгового виконання {{jsxref("Operators/new", "конструкторів", "", 1)}} до об'єкта, подібно до Java. У наступному прикладі ми створимо глобальний метод {{jsxref("Function")}} під назвою construct
, котрий дозволить використовувати подібний до масиву об'єкт з конструктором замість списку аргументів.
Function.prototype.construct = function(aArgs) { var oNew = Object.create(this.prototype); this.apply(oNew, aArgs); return oNew; };
Заувага: Метод Object.create(),
що використовується вище, є відносно новим. В якості альтернативних методів, будь ласка, розгляньте наступні підходи:
Використання {{jsxref("Object/proto", "Object.__proto__")}}:
Function.prototype.construct = function (aArgs) { var oNew = {}; oNew.__proto__ = this.prototype; this.apply(oNew, aArgs); return oNew; };
Function.prototype.construct = function(aArgs) { var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr(); };
Конструктор {{jsxref("Function")}}:
Function.prototype.construct = function (aArgs) { var fNewConstr = new Function(""); fNewConstr.prototype = this.prototype; var oNew = new fNewConstr(); this.apply(oNew, aArgs); return oNew; };
Приклад використання:
function MyConstructor() { for (var nProp = 0; nProp < arguments.length; nProp++) { this['property' + nProp] = arguments[nProp]; } } var myArray = [4, 'Всім привіт!', false]; var myInstance = MyConstructor.construct(myArray); console.log(myInstance.property1); // виведе 'Всім привіт!' console.log(myInstance instanceof MyConstructor); // виведе 'true' console.log(myInstance.constructor); // виведе 'MyConstructor'
Заувага: Цей не рідний метод Function.construct
не буде працювати з деякими вбудованими конструкторами; такими, як {{jsxref("Date")}}, наприклад. У таких випадках, ви маєте використовувати метод {{jsxref("Function.prototype.bind")}} (наприклад, уявіть собі такий масив, що використовується з конструктором {{jsxref("Global_Objects/Date", "Date")}}: [2012, 11, 4]
; у такому випадку вам доведеться написати щось по типу: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()
. Це не найкращий підхід, і, мабуть, не варто це робити у будь-якому виробничому середовищі).
Специфікація | Статус | Коментар |
---|---|---|
{{SpecName('ES3')}} | {{Spec2('ES3')}} | Початкове визначення. Реалізовано у JavaScript 1.3. |
{{SpecName('ES5.1', '#sec-15.3.4.3', 'Function.prototype.apply')}} | {{Spec2('ES5.1')}} | |
{{SpecName('ES6', '#sec-function.prototype.apply', 'Function.prototype.apply')}} | {{Spec2('ES6')}} | |
{{SpecName('ESDraft', '#sec-function.prototype.apply', 'Function.prototype.apply')}} | {{Spec2('ESDraft')}} |
The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
{{Compat("javascript.builtins.Function.apply")}}