Зачем вызывать "apply" вместо прямого вызова функции?
Когда я смотрел на исходный код Raphael или G.Raphael или других библиотек, я заметил, что разработчик делает что-то вроде этого:
var val = Math.max.apply(Math, data_array);
Почему бы просто не вызвать функцию напрямую, например:
var val = Math.max(data_array);
Благодарю.
5 ответов
Я думаю, что объяснение из Mozilla Docs хорошо описывает это:
Вы можете назначить другой объект this при вызове существующей функции. это относится к текущему объекту, вызывающему объекту. С помощью apply вы можете написать метод один раз, а затем наследовать его в другом объекте, без необходимости переписывать метод для нового объекта.
apply очень похож на call, за исключением того типа аргументов, который он поддерживает. Вы можете использовать массив аргументов вместо именованного набора параметров. С помощью apply вы можете использовать литерал массива, например fun.apply(this, [name, value]), или объект Array, например fun.apply(this, new Array(name, value)).
Что касается параметров:
thisArg Определяет значение этого внутри веселья. Если thisArg имеет значение null или не определено, это будет глобальный объект. В противном случае это будет равно Object(thisArg) (который является thisArg, если thisArg уже является объектом, или String, Boolean или Number, если thisArg является примитивным значением соответствующего типа). Поэтому всегда верно, что typeof this == "object" при выполнении функции.
argsArray Массив аргументов для объекта, определяющий аргументы, с которыми должен вызываться fun, или ноль или неопределенный, если никакие аргументы не должны быть предоставлены функции.
Документы дают хороший пример варианта использования для применения. В приведенном ниже примере apply используется для создания цепочки конструктора:
function product(name, value)
{
this.name = name;
if (value >= 1000)
this.value = 999;
else
this.value = value;
}
function prod_dept(name, value, dept)
{
this.dept = dept;
product.apply(this, arguments);
}
prod_dept.prototype = new product();
// since 5 is less than 1000 value is set
var cheese = new prod_dept("feta", 5, "food");
// since 5000 is above 1000, value will be 999
var car = new prod_dept("honda", 5000, "auto");
Обратите внимание, что в prod_dept
конструктор this
поставляется относится к prod_dept
объект и arguments
массив аргументов, передаваемых product
конструктор.
Math.max не будет принимать список по умолчанию. "apply" позволяет распаковать список с аргументами, чтобы max работал правильно.
Зачем вызывать "apply" вместо прямого вызова функции? Давайте иметь фрагмент:
var obj = {a: "apply"};
func.call(obj, "parameter");
function func(para) {
if(this.a === "apply"){
console.log('apply');
}
}
Здесь мы можем видеть, что мы используем 'this'
(контекст) внутри функции. Если мы напрямую вызываем функцию, чем у нас нет контекста, то это займет window
контекст, который не так. Итак, если вы используете контекст внутри своей функции, чем использовать apply
метод.
Вообще вы бы использовали apply()
а также call()
чтобы иметь возможность установить контекст или объект, к которому принадлежит вызывающая функция. Затем функция фактически становится методом этого объекта / контекста, который полезен, если вам нужно получить доступ к полям контекста.
Вот как Javascript изначально вызывает функции:
- Составьте список аргументов (argList) из параметров 1 до конца
- Первый параметр thisValue
- Вызвать функцию с этим значением thisValue и argList в качестве списка аргументов.
Ссылка: Понимание вызова функций JavaScript и "этого" Иегуда Кац
Таким образом, при непосредственном вызове функции вы фактически неявно передаете в контекст функции по умолчанию. Javascript проходит 'window'
или же 'undefined'
в качестве контекста, когда вы не указываете это с помощью call()
или же apply()
Этот ответ также дает пример, который может помочь в понимании использования
.apply
часто используется, когда целью является вызов переменной функции со списком значений аргументов, например
Math.max([value1[,value2, ...]])
Функция возвращает наибольшее из нуля или более чисел.
Math.max(10, 20); // 20
Math.max(-10, -20); // -10
Math.max(-10, 20); // 20
Math.max()
Метод не позволяет передавать в массив. Если у вас есть список значений, из которых вам нужно получить наибольшее, вы обычно вызываете эту функцию с помощью Function.prototype.apply (), например
Math.max.apply(null, [10, 20]); // 20
Math.max.apply(null, [-10, -20]); // -10
Math.max.apply(null, [-10, 20]); // 20
Однако, начиная с ECMAScript 6, вы можете использовать оператор распространения:
Оператор распространения позволяет развернуть выражение в местах, где ожидаются несколько аргументов (для вызовов функций) или несколько элементов (для литералов массива).
Math.max(...[10, 20]); // 20
Math.max(...[-10, -20]); // -10
Math.max(...[-10, 20]); // 20
При вызове функции с помощью оператора переменной можно даже добавить дополнительные значения, например
Math.max(...[10, 20], 50); // 50
Math.max(...[-10, -20], 50); // 50