【问题标题】:Is there any benefit to call Reflect.apply() over Function.prototype.apply() in ECMAScript 2015?在 ECMAScript 2015 中调用 Reflect.apply() 而不是 Function.prototype.apply() 有什么好处吗?
【发布时间】:2016-01-10 15:39:02
【问题描述】:

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

Reflect.apply(myFunction, myObject, args);

代替:

myFunction.apply(myObject, args);

【问题讨论】:

  • 引用MDN,“不那么冗长,更容易理解”。

标签: javascript functional-programming ecmascript-6


【解决方案1】:

您可以在规范中比较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

【讨论】:

  • 第二个差异可以通过Function.prototype.apply.call轻松克服
  • @BenjaminGruenbaum 但这更长。并假设没有疯狂的脚本阻止 Function.prototype.applyFunction.prototype 继承,也没有添加自定义 call 自己的方法。
  • 如果您在自己的代码中覆盖 Function.prototype.apply,愿上帝怜悯您的灵魂。
  • @Thomson undefined 可能被具有另一个值的局部变量所遮蔽。 void 0 总是返回原始的未定义值。
  • 如果 apply 因某些功能而被遮蔽,则可能是出于某种原因 - 记录、模拟等。使用 Reflect.apply() 将绕过所有这些。
【解决方案2】:

另请参阅 SO 问题 What does the Reflect object do in JavaScript?,该问题在最佳答案中包含此文本:

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

我的理解是,在以前的 JS 迭代中,与“反射”相关的工具已经分散在语言周围,作为 Object 原型和 Function 原型的一部分。 Reflect 对象旨在将它们集中在一个屋檐下。

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

【讨论】:

  • 这是唯一让我信服的解释
【解决方案3】:

我能想到的一个用途是在流程管理或执行函数数组的函数中使用 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)
  })
}

因为你有更多的控制权。

【讨论】:

    猜你喜欢
    • 2020-08-27
    • 1970-01-01
    • 2020-12-22
    • 2018-08-17
    • 2012-11-29
    • 1970-01-01
    • 2011-12-09
    • 2012-05-18
    • 2011-10-29
    相关资源
    最近更新 更多