在 ECMAScript 2015 中调用 Reflect.apply() 而不是 Function.prototype

Is there any benefit to call Reflect.apply() over Function.prototype.apply() in ECMAScript 2015?

本文关键字:prototype Function apply 2015 ECMAScript 调用 Reflect      更新时间:2023-09-26

我只是想知道是否有任何充分的理由打电话:

Reflect.apply(myFunction, myObject, args);

而不是:

myFunction.apply(myObject, args);

您可以在规范中比较Function.prototype.applyReflect.apply的定义。

基本上它们是等价的,但有区别:如果参数列表是nullundefinedFunction.prototype.apply将调用没有参数的函数,Reflect.apply将抛出。

function func() {
  return arguments.length;
}
func.apply(void 0, null); // 0
Reflect.apply(func, void 0, null); // TypeError: null is not a non-null object

另一个区别是,当你使用func.apply时,你假设

  • func是一个Function实例,即它继承自Function.prototype
  • func没有apply自己的财产,会给Function.prototype.apply阴影

Reflect.apply并不需要这样做。例如

var obj = document.createElement('object');
typeof obj; // "function" -- can be called
obj.apply; // undefined -- does not inherit from Function.prototype
Reflect.apply(obj, thisArg, argList); // -- works properly
var func = a => a;
func.apply = a => 0;
func.apply(void 0, [123]); // 0 -- Function.prototype.apply is shadowed by an own property
Reflect.apply(func, void 0, [123]); // 123 -- works properly

另请参阅SO问题"反射对象在JavaScript中做什么?",其中包括以下文本:

现在我们有了模块,对于之前在 Object 上定义的许多反射方法来说,"@reflect"模块是一个更自然的地方。出于向后兼容性的目的,Object 上的静态方法不太可能消失。但是,新方法可能应该添加到"@reflect"模块而不是对象构造函数中

我的理解是,在以前的JS迭代中,与"反射"相关的工具分散在语言中,作为对象原型和函数原型的一部分。Reflect目标是努力将它们集中在一个屋檐下。

因此,就您的问题而言,尽管存在差异(参见Oriol的答案(,但两者存在的原因是ES规范中普遍转向面向未来的反射工具。

我能想到的一种用途是在流管理或执行函数数组的函数中使用 Reflect.apply

function execFuncs(funcArr){
 var obj = this.someObj;
 funcArr.forEach(function(func){
    Reflect.apply(func,obj)
 });
}

哪个更方便

function execFuncs(funcArray){
  var obj = this.someObj;
  funcArray.forEach(function(func){
      func.prototype.apply(obj)
  })
}

因为你有更多的控制权。