你为什么要通过'null'到'应用'或者'呼叫'

Why would you pass 'null' to 'apply' or 'call'?

本文关键字:应用 或者 呼叫 null 为什么      更新时间:2023-09-26

根据此JavaScript参考:

null值是一个JavaScript文本,表示null或"空"值,即不存在对象值。它是JavaScript的基元值。

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

显式传递关键字this不是更清晰,或者至少更可读吗?再说一遍,在这一点上,我可能不明白你为什么要使用null

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

如果函数内没有要为this指针指定的值,并且您正在调用的函数不需要特定的this值才能正常工作。

明确传递关键字不是更清楚吗?或者至少更易于阅读。再说一遍,在这一点上,我可能不明白为什么你会使用null。

在您的特定情况下,可能最好通过Math对象:

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

虽然事实证明,传递什么作为Math.max.apply(...)的第一个参数并不重要(只是因为Math.max()的实现细节),但传递Math会将this指针设置为与Math.max(1,2,3)一样正常调用时设置的指针完全相同的指针,因此这是最安全的选项,因为您最好模拟对Math.max()的正常调用。

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

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

注意:将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指针来按预期执行其工作。

以null作为第一个参数调用apply就像在不为this提供任何对象的情况下调用函数一样。

apply方法的作用是什么?

apply()方法调用具有给定this值的函数,并且作为阵列(或类似阵列的对象)提供的CCD_ 32。

fun.apply(thisArg, [argsArray])

thisArg

这为呼吁娱乐提供了价值。请注意,这可能不是是该方法看到的实际值:如果该方法是中的函数非严格模式代码,null和undefined将被替换为全局对象和基元值将被装箱。

更多文档可在此处找到。

我发现这很有用的一种情况是,当我调用的函数已经绑定到特定上下文时。

因为绑定函数不能反弹,并且它们总是用传递到bind中的thisArg来调用,所以将thisArg传递到callapply中没有任何用处。来源:

bind()函数创建一个新的绑定函数(BF)。。。。当调用绑定函数时,它会调用[[BoundTargetFunction]]上的内部方法[[Call]],并带有以下参数Call(boundThis, args)

这里有一个例子:

class C {
  constructor() {
    this.a = 1;
  }
}
function f(n, m) {
  console.log(this.a + n + m);
}
let c = new C();
var boundF = f.bind(c, 2); // the context `c` is now bound to f
boundF.apply(null, [3]); // no reason to supply any context, since we know it's going to be `c`

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

JavaScript中的null是什么?

null值是一个文本(而不是像undefined那样的全局对象的属性)。它是JavaScript的基元值之一。

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

fun.apply(thisArg,[argsArray])

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

argsArray:一个类似数组的对象,指定应该调用fun的参数,如果不应该向函数提供参数,则为null或未定义。从ECMAScript 5开始,这些参数可以是类似于泛型数组的对象,而不是数组。有关浏览器兼容性信息,请参见下文。

如果您正在使用"严格模式",则建议通过this或数学作为参数。

Apply在您希望将执行某些操作的责任传递给在运行时确定的函数,并将可变数量的参数传递给该函数时非常有用。当你这样做的时候,你可能有也可能没有任何合适的"这个"上下文。

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

我希望能够提出这样的事件:

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.recallback)时,应用程序用于传递数量可变的参数。在这里,我允许侦听器在定义侦听器时为其事件处理程序提供this上下文,但该上下文可能没有定义,或者可能为null,这完全可以。

很长一段时间以来,raise函数甚至不方便使用任何回调上下文。我最终遇到了对它的需求,所以我支持它,但大多数时候我并不真正需要或使用它。