call/apply/bind
日常编码中被开发者用来实现 “对象冒充”,也即 “显示绑定 this
“。
面试题:“call/apply/bind源码实现”,事实上是对 JavaScript 基础知识的一个综合考核。
相关知识点:
- 作用域;
- this 指向;
- 函数柯里化;
- 原型与原型链;
call/apply/bind 的区别
- 三者都可用于显示绑定
this
; call/apply
的区别方式在于参数传递方式的不同;fn.call(obj, arg1, arg2, ...)
, 传参数列表,以逗号隔开;fn.call(obj, [arg1, arg2, ...])
, 传参数数组;
bind
返回的是一个待执行函数,是函数柯里化的应用,而call/apply
则是立即执行函数
思路初探
|
|
call 的源码实现
初步思路有个大概,剩下的就是完善代码。
|
|
知识点补充:
- ES6 新的原始数据类型
Symbol
,表示独一无二的值; Object.create(null)
创建一个空对象
|
|
使用 Object.create(null)
创建的空对象,不会受到原型链的干扰。原型链终端指向 null
,不会有构造函数,也不会有 toString
、 hasOwnProperty
、valueOf
等属性,这些属性来自 Object.prototype
。有原型链基础的伙伴们,应该都知道,所有普通对象的原型链都会指向 Object.prototype
。
所以 Object.create(null)
创建的空对象比其它两种方式,更干净,不会有 Object
原型链上的属性。
ES5 版本:
- 自行处理参数;
- 自实现
Symobo
|
|
apply 的源码实现
call
的源码实现,那么 apply
就简单,两者只是传递参数方式不同而已。
bind 的源码实现
bind
与call/apply
的区别就是返回的是一个待执行的函数,而不是函数的执行结果;bind
返回的函数作为构造函数与new
一起使用,绑定的this
需要被忽略;
调用绑定函数时作为this参数传递给目标函数的值。 如果使用new运算符构造绑定函数,则忽略该值。 —— MDN
|
|
不少伙伴还会遇到这样的追问,不使用 call/apply
,如何实现 bind
?
骚年先别慌,不用 call/apply
,不就是相当于把 call/apply
换成对应的自我实现方法,算是偷懒取个巧吧。
本篇 call/apply/bind
源码实现,算是对之前文章系列知识点的一次加深巩固。
“心中有码,前路莫慌。”
参考文档:
更多前端基石搭建,尽在 Github,期待 Star!
https://github.com/ZengLingYong/blog
作者:以乐之名
本文原创,有不当的地方欢迎指出。转载请指明出处。