Ori*_*iol 14

你可以比较的定义Function.prototype.apply,并Reflect.apply在规范中.

基本上它们是等价的,但是有区别:如果参数列表是null或者undefined,Function.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
Run Code Online (Sandbox Code Playgroud)

另一个区别是,当你使用时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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

  • 如果你在自己的代码中覆盖`Function.prototype.apply`,上帝可能会怜悯你的灵魂. (8认同)
  • 第二个区别可以通过`Function.prototype.apply.call`轻松克服 (5认同)
  • @BenjaminGruenbaum但这更长。并假设没有疯狂的脚本阻止过Function.prototype.apply从Function.prototype继承,也没有添加自定义的call自己的方法。 (2认同)
  • @Thomson`undefined`可能被带有另一个值的局部变量所遮盖。“ void 0”总是返回原始的未定义值。 (2认同)
  • 如果`apply` 被某些函数遮蔽了,那可能是出于某种原因——日志记录、模拟等。使用`Reflect.apply()` 可以绕过所有这些。 (2认同)

N3d*_*st4 9

另请参阅SO问题Reflect对象在JavaScript中的作用是什么?,在最佳答案中包含此文字:

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

我的理解是,在以前的JS迭代中,与"反射"相关的工具已经分散在语言中,作为Object原型和Function原型的一部分.的Reflect目的是使他们在一个屋檐下的努力.

因此,就你的问题而言,虽然存在差异(参见Oriol的答案),但两者存在的原因是在ES规范中对未来验证反射工具的一般转移.

  • 这是唯一让我信服的解释 (2认同)