Как работает Math.max.apply ()?

82

Как Math.max.apply()работает ?.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
  <script>
      var list = ["12","23","100","34","56",
                                    "9","233"];
      console.log(Math.max.apply(Math,list));    
  </script>
</body>
</html>

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max

Приведенный выше код находит максимальное число в списке. Может ли кто-нибудь сказать мне, как работает приведенный ниже код ?. Кажется, это работает, если я пройдуnull or Math.

console.log(Math.max.apply(Math,list));

Есть ли у всех метод user-defined/Native functionsвызова и применения, который мы можем использовать?

Шейн
источник

Ответы:

139

applyпринимает массив и применяет его в качестве параметров к фактической функции. Так,

Math.max.apply(Math, list);

можно понимать как,

Math.max("12", "23", "100", "34", "56", "9", "233");

Итак, applyэто удобный способ передать массив данных в качестве параметров функции. Помните

console.log(Math.max(list));   # NaN

не будет работать, потому maxчто не принимает массив в качестве входных данных.

Есть еще одно преимущество использования apply: вы можете выбрать свой собственный контекст. Первый параметр, который вы передаете applyлюбой функции, будет thisвнутри этой функции. Но maxне зависит от текущего контекста. Таким образом, все будет работать вместо Math.

console.log(Math.max.apply(undefined, list));   # 233
console.log(Math.max.apply(null, list));        # 233
console.log(Math.max.apply(Math, list));        # 233

Поскольку applyфактически определено вFunction.prototype , любой допустимый объект функции JavaScript applyпо умолчанию будет иметь функцию.

четыре глаза
источник
3
@Shane, потому что он работает, даже когда мы устанавливаем контекст на undefinedили null:) Если бы вы maxпопытались получить доступ / изменить что-либо в контексте, это не удалось бы, если для контекста установлено значение undefinedили null.
thefourtheye
2
@NiCkNewman Фактически, Math.maxне будет использовать первый параметр, поскольку ему не нужен контекст. Он работает только с данными, которые он получает в аргументах.
thefourtheye
1
@NiCkNewman Это слишком широко, чтобы обсуждать в разделе комментариев. Но эта статья thisбудет хорошей отправной точкой. Она также имеет раздел , callиapply в котором подробно это.
thefourtheye
2
Лучшее объяснение .apply () когда-либо!
Microcipcip
1
Почему ноль или математика?
17

Может ли кто-нибудь сказать мне, как работает приведенный ниже код?

Math.max.apply(Math,list)

Вызывает Math.maxфункцию с Mathобъектом, который будет использоваться в качестве thisссылки в реализации функции (теле) иlist передаваться в качестве аргументов.

Таким образом, это в конечном итоге равно

Math.max("12","23","100","34","56", "9","233")

Кажется, это работает, если я передаю null или Math.

Очевидно, что Math.maxреализация не использует переменную экземпляра - для этого нет причин. Собственная реализация просто перебирает argumentsи находит максимальное значение.

Все ли пользовательские / собственные функции имеют метод call и apply, который мы можем использовать?

Да, каждую функцию можно вызвать с помощью callилиapply

Рекомендации:

Зеркмс
источник
3

Я начну с того , Math.max(...numbers)и Function.prototype.apply()должны использоваться только для массивов с относительно небольшим числом элементов. (...) и apply либо завершится ошибкой, либо вернет неправильный результат, если массив слишком велик

Math.max.apply(null | undefined | Math, numbers)то же самое, что Math.max(...numbers)я бы рекомендовал Math.max(...numbers)по эстетическим соображениям.

const numbers = [5, 6, 2, 3, 7];

const max = Math.max(...numbers);

console.log('max:', max);
// expected output: 7

const min = Math.min(...numbers);

console.log('min:', min);
// expected output: 2

Если вам нужно найти максимальный элемент в числовом массиве, который очень велик: используйте Array.reduce()метод.

Array.reduce() может использоваться для поиска максимального элемента в числовом массиве путем сравнения каждого значения:

const numbers = [5, 6, 2, 3, 7];
const getMax = (numbers) => numbers.reduce((a, b) => Math.max(a, b));

const getMin = (numbers) => numbers.reduce((a, b) => Math.min(a, b));
	
const max = getMax(numbers)
const min = getMin(numbers)

console.log('max:', max)
console.log('min:', min)

Заключение:

Относительно небольшой числовой массив: используйте Math.max(...numbers) числовой массив: используйте очень большой числовой массив: используйте Array.reduce()метод

воксун
источник
1
Движок JavaScriptCore имеет жестко заданный предел аргументов 65536, поэтому при использовании apply () вы должны убедиться, что размер вашего массива всегда будет меньше.
Chaarmann
2

Math.max (значение1, значение2, ...)

Math.max(1, 2, 3); // Math.max([value1[, value2[, ...]]])
value1, value2...являются параметрами и должны быть числами MDN Math.max

Вы не можете передавать в arrayкачестве Math.maxпараметров. Чтобы передать массив, вы должны использоватьapply .

Применять

Первый параметр apply - thisэто второй array. Математические методы эквивалентны статическим в других языках, что означает, что в отличие от них не требуется экземпляр объекта, array.prototype.sliceпоэтому вам не нужно передаватьthis в этом случае .

пример

var arr = [1, 2, 3];

Math.max(1, 2, 3);  // -> 3
Math.max(arr);      // -> NaN (Not a Number)
Math.max.apply(null, arr);  // Math.max.apply(null, [1, 2, 3]) -> Math.max(1, 2, 3) -> 3

arr.slice(1);  // -> returns Array [2, 3]
Array.prototype.slice.call(arr, 1); // Array.prototype.slice.call([1, 2, 3], 1) == [1, 2, 3].slice(1)

Если вы хотите передать массив в качестве параметра, который вы должны использовать apply, в противном случае используйте call.

a pply = a rray
c all = c omma separated
Подробнее о вызове и применении

rflw
источник