探索 Reflect.apply 与 Function.prototype.apply 的区别
众所周知, ES6 新增了一个全局、内建、不可构造的 Reflect
对象,并提供了其下一系列可被拦截的操作方法。其中一个便是 Reflect.apply()
了。下面探究下它与传统 ES5 的 Function.prototype.apply()
之间有什么异同。
函数签名
MDN 上两者的函数签名分别如下:
Reflect.apply(target, thisArgument, argumentsList)
function.apply(thisArg, [argsArray])
而 TypeScript 定义的函数签名则分别如下:
declare namespace Reflect { function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any; }
interface Function { apply(this: Function, thisArg: any, argArray?: any): any; }
它们都接受一个提供给被调用函数的 this 参数和一个参数数组(或一个类数组对象, array-like object )。
可选参数
可以最直观看到的是, function.apply()
给函数的第二个传参「参数数组」是可选的,当不需要传递参数给被调用的函数时,可以不传或传递 null
、 undefined
值。而由于 function.apply()
只有两个参数,所以实践中连第一个参数也可以一起不传,原理上可以在实现中获得 undefined
值。
(function () { console.log('test1') }).apply() // test1 (function () { console.log('test2') }).apply(undefined, []) // test2 (function () { console.log('test3') }).apply(undefined, {}) // test3 (function (text) { console.log(text) }).apply(undefined, ['test4']) // test4
而 Reflect.apply()
则要求所有参数都必传,如果希望不传参数给被调用的函数,则必须填一个空数组或者空的类数组对象(纯 JavaScript 下空对象也可以,若