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

12

在查看raphael、g.raphael或其他库的源代码时,我注意到开发者会这样做:

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

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

var val = Math.max(data_array);

谢谢。


好的,我看到Math.max需要两个参数,所以我只调用Math.max(array)的例子是行不通的。所以,我的问题是,我的问题中的第一行代码如何在数据数组的每个元素上调用“max”? - codecraig
2
Javascript 的 .apply.call 真是太棒了! - Rudie
5个回答

13

默认情况下,Math.max不接受列表作为参数。使用"apply"可以将列表解包成参数,以便max函数正常工作。


12

我认为Mozilla文档中的解释已经很清楚了:

在调用现有函数时,您可以分配不同的this对象。 this指的是当前对象,即调用对象。使用apply,您可以编写一次方法,然后在另一个对象中继承它,而无需为新对象重写该方法。

apply与call非常相似,除了它支持的参数类型不同。您可以使用参数数组而不是命名的参数集。使用apply,您可以使用数组字面量,例如fun.apply(this,[name,value]),或Array对象,例如fun.apply(this,new Array(name,value))。

至于参数:

确定fun内部的this值。如果thisArg为null或undefined,则this将是全局对象。否则,this将等于Object(thisArg)(如果thisArg已经是一个对象,则是thisArg;如果thisArg是相应类型的原始值的字符串、布尔值或数字,则是String、Boolean或Number)。因此,在函数执行时,typeof this == "object"总是成立。

argsArray是一个参数数组,用于指定使用哪些参数调用fun,如果不提供任何参数,则为null或undefined。

文档给出了一个关于apply的用例示例。在下面的示例中,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构造函数的参数数组。


prod_dept.prototype = new product(); 这行代码完全不需要,可以删除以简化代码! - Pratik Joshi

2

为什么要使用“apply”来调用函数而不是直接调用呢?我们来看一段代码:

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

在这里,我们可以看到在一个函数内使用了'this'(上下文)。如果我们直接调用一个函数,那么我们就没有任何上下文,这时它会采用window上下文,这是错误的。所以,如果你在函数内使用上下文,那么就使用apply方法。


0
通常情况下,您可以使用apply()call()来设置调用函数所属的上下文或对象。然后该函数有效地成为该对象/上下文的方法,如果您需要访问上下文的字段,则非常有帮助。
这就是Javascript本地调用函数的方式:
1.将参数1到最后一个参数制作成参数列表(argList)
2.第一个参数是thisValue 3.以thisValue设置为this,并将argList作为其参数列表调用该函数
参考:理解JavaScript函数调用和“this” by Yehuda Katz 因此,直接调用函数时,实际上隐式地向函数传递了默认上下文。当您未使用call()apply()指定上下文时,Javascript会将'window''undefined'作为上下文传递。

这个 答案 还提供了一个例子,有助于理解用法。


0

.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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接