为什么要调用“apply”而不是直接调用函数?

时间:2011-05-09 12:03:45

标签: javascript splat

在查看raphael或g.raphael或其他库的源代码时,我注意到开发人员做了类似这样的事情:

var val = Math.max.apply(Math, data_array);

为什么不直接调用函数,例如:

var val = Math.max(data_array);

感谢。

5 个答案:

答案 0 :(得分:13)

默认情况下,Math.max不接受列表。 “apply”允许您将列表解压缩到参数,以便max可以正常工作。

答案 1 :(得分:11)

我认为Mozilla Docs的解释很好地描述了它:

  

您可以指定其他对象   调用现有函数时。    this 指的是当前对象,   调用对象。有了申请,你可以   写一个方法然后继承   它在另一个对象中,没有   重写新方法   对象

     

apply非常类似于call,除了   对于它支持的参数类型。   您可以使用参数数组   一组命名的参数。同   apply,你可以使用数组文字,   例如,fun.apply(this,[name,   value])或一个Array对象   fun.apply(这个,新的   数组(名称,值))。

至于参数:

  

<强> thisArg       在乐趣中确定 this 的值。如果 thisArg 为null或   undefined,这个将是全球性的   宾语。否则,这将是平等的   to Object(thisArg)(这是thisArg   如果thisArg已经是一个对象,或者一个   如果thisArg,则为String,Boolean或Number   是一个原始的价值   相应的类型)。因此它是   总是这个==的类型   函数执行时的“对象”。

     

<强> argsArray       对象的参数数组,指定与之对应的参数   应该调用fun,或null或   如果没有参数,则为undefined   提供给该职能部门。

文档提供了一个用于应用的用例的好例子。在下面的示例中,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的参数数组构造函数。

答案 2 :(得分:2)

为什么要调用“apply”而不是直接调用函数?我们有一个片段:

var obj = {a: "apply"};
func.call(obj, "parameter");
function func(para) {
    if(this.a === "apply"){
        console.log('apply'); 
     }
} 

在这里我们可以看到我们在函数中使用'this'(上下文),如果我们直接调用func而不是没有任何上下文,那么它将需要window上下文,这是错误。因此,如果您在函数中使用上下文而不是使用apply方法。

答案 3 :(得分:0)

当意图使用参数值列表调用可变参数函数时,经常使用

.apply,例如

Math.max([value1[,value2, ...]])函数返回0或0以上的最大数字。

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开始,您可以使用spread operator

  

扩展运算符允许在需要多个参数(用于函数调用)或多个元素(用于数组文字)的位置扩展表达式。

Math.max(...[10, 20]); // 20
Math.max(...[-10, -20]); // -10
Math.max(...[-10, 20]); // 20

使用variadic运算符调用函数时,甚至可以添加其他值,例如

Math.max(...[10, 20], 50); // 50
Math.max(...[-10, -20], 50); // 50

答案 4 :(得分:0)

通常,您可以使用apply()call()来设置调用函数所属的上下文或对象。然后,该函数有效地成为该对象/上下文的方法,如果您需要访问上下文的字段,这将是有用的。

这就是Javascript本身调用函数的方式:

  1. 从参数1到结尾
  2. 创建一个参数列表(argList)
  3. 第一个参数是thisValue
  4. 使用此set调用thisValue并将argList作为其参数列表
  5. 调用该函数

    参考:Understanding JavaScript Function Invocation and "this"来自Yehuda Katz

    因此,当直接调用函数时,实际上是隐式地将默认上下文传递给函数。当您未使用'window''undefined'

    指定时,Javascript会将call()apply()作为上下文传递

    answer还提供了一个可能有助于理解用法的示例