为什么要将'null'传递给'apply'或'call'?

时间:2015-11-10 21:36:57

标签: javascript

根据this JavaScript reference

  

值null是表示null或“空”的JavaScript文字   值,即不存在对象值。它是JavaScript之一   原始价值观。

function getMax(arr){
  return Math.max.apply(null, arr);  
}

不会明确地传递关键字this更清晰,或者至少更具可读性?然后,在这一点上,我可能不明白你为什么要使用null

5 个答案:

答案 0 :(得分:11)

使用null作为第一个参数调用apply就像调用函数而不为this提供任何对象。

apply方法有什么作用?

  

apply()方法调用具有给定this值的函数   arguments作为数组(或类数组对象)提供。

fun.apply(thisArg, [argsArray])
  

thisArg

     

为乐趣召唤提供的价值。请注意,这可能不是   是方法看到的实际值:如果方法是函数   非严格模式代码,null和undefined将替换为   全局对象和原始值将被装箱。

可以找到进一步的文档here

答案 1 :(得分:10)

  

为什么你会通过' null'要适用'或者打电话'?

如果没有值,您希望为函数内的this指针指定值,并且您调用的函数不会期望特定的this值以便正常运行。< / p>

  

不会明确地传递关键字这个更清楚吗?或至少   更具人性化。然后在这一点上我可能不明白为什么   你会使用null。

在您的具体情况下,最好的方法是Math对象:

function getMax(arr){
  return Math.max.apply(Math, arr);  
}

虽然事实证明,作为Math.max.apply(...)的第一个参数传递的内容并不重要(仅因为Math.max()的实现细节),但传递Maththis指向与Math.max(1,2,3)正常调用时设置的完全相同的指针,因此这是最安全的选项,因为您最好模拟对Math.max()的正常调用。< / p>

  

为什么你会通过&#39; null&#39;要适用&#39;或者打电话&#39;?

以下是一些更多详细信息...使用.call().apply()时,如果您没有要设置null的特定值,则可以传递this指向并且您知道您正在调用的函数不期望this具有任何特定值(例如,它在其实现中不使用this)。

注意:将null.apply().call()一起使用通常仅使用仅出于命名空间原因的方法的函数,而不是出于面向对象的原因。换句话说,函数max()Math对象上的一个方法,只是因为命名空间的原因,而不是因为Math对象具有方法.max()需要的实例数据访问。

如果你这样做:

   function foo() {
       this.multiplier = 1;
   }

   foo.prototype.setMultiplier = function(val) {
       this.multiplier = val;
   }

   foo.prototype.weightNumbers = function() {
       var sum = 0;
       for (var i = 0; i < arguments.length; i++) {
           sum += (arguments[i] * this.multiplier);
       }
       return sum / arguments.length;
   }

   var x = new foo();
   x.setMultiplier(3);
   var numbers = [1, 2, 3]
   console.log(x.weightNumbers.apply(x, numbers));

当您调用.apply()的方法需要访问实例数据时,您必须将相应的对象作为第一个参数传递,以便该方法具有正确的this指针来完成其工作预期

答案 2 :(得分:1)

我回答这个问题有点迟了。我会尝试在这里给出一个很长的描述性解释。

  

JavaScript中的null是什么?

值null是一个文字(不是像undefined那样的全局对象的属性)。它是JavaScript的原始值之一。

在API中,通常会在可以预期对象但没有对象相关的位置检索null。

  

fun.apply(thisArg,[argsArray])

thisArg :为乐趣调用提供的值。请注意,这可能不是方法看到的实际值:如果方法是非严格模式代码中的函数,则null和undefined将替换为全局对象,并且原始值将被装箱。

argsArray :一个类似数组的对象,指定应该调用fun的参数,如果不应该为函数提供参数,则为null或undefined。从ECMAScript 5开始,这些参数可以是类似通用数组的对象而不是数组。请参阅下面的浏览器兼容性信息

  

如果您使用&#39;严格模式&#39;,则建议通过此或   数学作为参数。

答案 3 :(得分:1)

我发现这很有用的一种情况是,我正在调用的功能已经绑定到特定的上下文。

因为绑定函数无法反弹,并且始终使用传递给thisArg的{​​{1}}来调用它们,所以将bind传递给{{1}毫无用处}或thisArg。来自source

  

call函数将创建一个新的绑定函数(BF)。...调用绑定函数时,它将在apply上调用内部方法bind(),并带有以下参数{{1 }}。

这是一个例子:

[[Call]]

答案 4 :(得分:1)

当您希望将对某项操作的责任传递给在运行时确定的函数,并将可变数量的参数传递给该函数时,应用很有用。在执行此操作时,您可能有也可能没有任何适当的“此”上下文。

例如,我使用编写的库来方便侦听和引发使用apply的应用程序事件。

我希望能够引发这样的事件:

EventManager.raise('some:event-name', arg1, arg2, arg3, ..);

..,并使用该参数列表(arg1,arg2等)调用该事件的所有已注册处理程序。因此,在raise函数中,它将遍历为该事件名称注册的处理程序并调用它们,并传递除事件名称之外的所有传入参数,例如:

var args = [];
Array.prototype.push.apply(args, arguments);
args.shift();
for (var l in listeners) {
    var listener = listeners[l];
    listener.callback.apply(listener.context, args);
}

调用注册的处理程序(listener.callback)时,apply用于传递可变数量的参数。在这里,我已允许侦听器在定义侦听器时为其事件处理程序提供此上下文,但是该上下文可能未定义,或者可能为null,这很好。

很长一段时间内,raise函数甚至都没有促进使用任何回调上下文。最终我遇到了对它的需求,因此我对它提供了支持,但是大多数时候我并不是真的需要或使用它。