解析bind绑定call函数的作用及相关JavaScript代码逻辑
先把原代码贴出来,方便对照:
var eObject = Object, DeObject_bind = eObject.bind, neObject_call = eObject.call, object_call = neObject_call.bind(DeObject_bind, neObject_call), reObject_apply = eObject.apply, object_apply = object_call(reObject_apply)
先理清基础前提
所有函数(包括Object构造函数)的bind/call/apply方法,本质上都来自Function.prototype。比如Object.bind就是Function.prototype.bind的引用,只是通过Object这个函数调用而已。
逐行拆解逻辑
var eObject = Object
只是给Object构造函数起了个短别名,没特殊逻辑。DeObject_bind = eObject.bind
把Function.prototype.bind存到DeObject_bind里——因为eObject是Object,它的bind方法继承自Function.prototype。neObject_call = eObject.call
和上面同理,把Function.prototype.call存到neObject_call里。object_call = neObject_call.bind(DeObject_bind, neObject_call)
这是核心第一步,拆解一下:neObject_call是Function.prototype.call,调用它的bind方法会生成一个新函数。- 新函数的
this被绑定到DeObject_bind(也就是Function.prototype.bind),同时预设了第一个参数是neObject_call(也就是Function.prototype.call)。 - 当你调用
object_call(目标函数)时,实际执行的是:Function.prototype.call.call(Function.prototype.bind, Function.prototype.call, 目标函数)。 - 再简化:这等价于
Function.prototype.bind.call(Function.prototype.call, 目标函数),最终会返回目标函数.call的绑定版本——也就是一个函数,调用它时传入context和参数列表,就等价于目标函数.call(context, 参数1, 参数2...)。
reObject_apply = eObject.apply
把Function.prototype.apply存到reObject_apply里,和前面的call逻辑一致。object_apply = object_call(reObject_apply)
调用object_call并传入reObject_apply(也就是Function.prototype.apply),根据上面的逻辑,这会返回一个绑定好的函数:- 调用
object_apply(目标函数, context, 参数数组)时,等价于目标函数.apply(context, 参数数组)。
- 调用
总结这段代码的作用
其实就是绕了个弯,创建了两个通用工具函数:
object_call:传入一个函数,返回该函数的call方法绑定版本,调用时直接传上下文和参数即可,不用写.call。object_apply:直接是一个通用的apply调用工具,传入目标函数、上下文、参数数组,就等价于调用该函数的apply方法。
这么写大概率是为了获取原生的call/apply方法,避免全局环境中这些方法被篡改,同时封装成更简洁的调用形式。
内容的提问来源于stack exchange,提问作者user871199

