in JavaScript

函数的arguments,注入及高阶函数

引子

在研究恶魔金字塔(Pyramid of Doom)的过程中,注意到 async 有这样的示例代码:

令人寻味的是这个回调函数callback。它不是调用者写的,而是由series()通过高阶函数的方式注入的。怎么注入的?答案是 arguments。事实上,async 完美的运用了函数arguments 的动态特性。

说到这个 arguments呢,它其实不是个数组,toString 会报告它是一种 [object Arguments] 类型的数据。诚如 MDN 所述:

The arguments object is a local variable available within all functions…

You can refer to a function’s arguments within the function by using the arguments object. This object contains an entry for each argument passed to the function, the first entry’s index starting at 0.

需要注意的是,Function对象只有在运行(call/apply)时,才会得到这个arguments对象,与你怎么声明这个函数签名没有关系。比如声明这么一个无参函数,实际调用你可以传入任意参数,arguments 能够感知:

并且,这个arguments只在函数的作用域内可见。它的出现:在函数运行时,位于函数体内。

有了arguments,再配合 高阶函数,实际上我们可以做很多事情,比如对任意函数进行注入——更具体一点,回到恶魔金字塔(Pyramid of Doom)问题中,调用函数和被调函数约定:每个被调函数的最后一个参数,将一定会被调用方传入一个回调函数,被调函数将自觉遵守约定,在逻辑执行完成前,callback it!   然后,主调方将各个被调函数织入队列,统一在其 arguments 末尾注入一个 callback函数。

实验

假设callback长这样:

被调函数callback时传入的arguments被转成一个Array,打印到console。

调用函数的注入高阶函数长这样:

它假设第一个参数一定是个Function,其余就是要注入的参数,对这个Function进行一次包装并返回(闭包应用),需要注意的是 fn.apply() 中的那个arguments是 Function运行时的自有参数,而不是injectArgs函数的参数。

假设有一个被调函数funcA:

它假设至少会有一个callback被传入,然后遵守约定,执行它。

那么,我们可以这么玩儿:

What  should happen:
dynamically mixin arguments

funcAInected 这个 funcA 被 injectArgs 包装后的代理函数,成功的将它的实际参数传递给了callback,它的执行链是:

funcA -> 传递funcA.arguments -> 转为callback.arguments -> callback执行 -> 返回 funcA。

 

打赏作者
您的支持将激励我继续创作!

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

Write a Comment

Comment