From 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:43:23 -0500 Subject: initial commit --- .../global_objects/function/apply/index.html | 239 +++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 files/uk/web/javascript/reference/global_objects/function/apply/index.html (limited to 'files/uk/web/javascript/reference/global_objects/function/apply') diff --git a/files/uk/web/javascript/reference/global_objects/function/apply/index.html b/files/uk/web/javascript/reference/global_objects/function/apply/index.html new file mode 100644 index 0000000000..78183d8102 --- /dev/null +++ b/files/uk/web/javascript/reference/global_objects/function/apply/index.html @@ -0,0 +1,239 @@ +--- +title: Function.prototype.apply() +slug: Web/JavaScript/Reference/Global_Objects/Function/apply +tags: + - Function + - JavaScript + - Довідка + - Функція + - метод +translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply +--- +
{{JSRef}}
+ +

Метод apply() викликає функцію із заданим значенням this та аргументами, переданими у вигляді масиву (або подібного до масиву об'єкта).

+ +
+

Заувага: Хоча синтаксис цієї функції є майже ідентичним до синтаксису {{jsxref("Function.call", "call()")}}, фундаментальна відмінність полягає в тому, що метод call() приймає список аргументів, тоді як метод apply() приймає єдиний масив аргументів.

+
+ +
+

Заувага: Коли першим аргументом є undefined або null, схожий результат можна отримати за допомогою оператора розпакування масивів.

+
+ +

{{EmbedInteractiveExample("pages/js/function-apply.html")}}

+ + + +

Синтаксис

+ +
function.apply(thisArg, [argsArray])
+ +

Параметри

+ +
+
thisArg
+
Значення this, передане для виклику у функцію function. Зазначте, що this може не бути фактичним значенням, яке бачить метод: якщо метод є функцією не у {{jsxref("Strict_mode", "строгому режимі", "", 1)}}, {{jsxref("null")}} та {{jsxref("undefined")}} будуть замінені глобальним об'єктом, а прості значення будуть запаковані. Цей аргумент є обов'язковим.
+
argsArray
+
Необов'язковий. Подібний до масиву об'єкт, що визначає аргументи, з якими функція має бути викликана, або {{jsxref("null")}} чи {{jsxref("undefined")}}, якщо жодних аргументів не має бути передано у функцію. Починаючи з ECMAScript 5, ці аргументи можуть бути загальними подібними до масиву об'єктами замість масиву. Дивіться нижче інформацію щодо {{anch("Сумісність_з_веб-переглядачами", "сумісності з веб-переглядачами")}}.
+
+ +

Значення, яке повертається

+ +

Результат виконання функції з вказаним значенням 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')}}
+ +

Сумісність з веб-переглядачами

+ + + +

{{Compat("javascript.builtins.Function.apply")}}

+ +
+ +

Див. також

+ + -- cgit v1.2.3-54-g00ecf