推荐答案
-- -------------------- ---- ------- ------------------------- - ----------------- -------- - -- ------- ---- --- ----------- - ----- --- ---------------------------------- - ---- -- ------ -- -- ----- -- --- ----------- - ----- ---- - ----- -- ------- ----- ---- - ---------- --- -- --------- ----- ------ - ---------------------- - -- ---- ---------- ------ ------- --- -- ------ --------------- ---------- ------ - ---- - -------- ------------------------ -- ------------------- -------------- - -------------- - ---------------- - --- ------- -- ----- ------ ------- --
本题详细解读
1. bind
函数的作用
bind()
方法会创建一个新的函数,当这个新函数被调用时,它的 this
关键字会被设置为传入的第一个参数,后续的参数将作为新函数的参数传递。bind
函数本质上是改变了函数执行时的 this
指向。
2. 实现步骤分解
参数检查:
- 判断调用
myBind
的是否是函数,如果不是,抛出TypeError
错误。
- 判断调用
保存原函数和
context
:- 用
self
保存原函数this
的引用,后续需要用apply
调用。 context
就是bind
方法的第一个参数,它将作为新函数执行时的this
上下文。
- 用
处理预置参数:
- 使用
...args
获取bind
时传入的预置参数。
- 使用
创建
fNOP
空函数:- 用于原型继承,避免修改原函数的原型。
创建返回函数
fBound
:- 这是
bind
方法返回的新函数。 - 使用
...boundArgs
获取新函数调用时传入的参数。 - 处理
this
:- 判断是否使用
new
调用:- 如果
this instanceof fBound
为true
, 说明是用new
调用的,此时this
就是要返回实例对象,不需要改变this
。 - 否则就用
context
作为this
上下文。
- 如果
- 使用
apply
方法调用原函数self
,并合并预置参数args
和新参数boundArgs
。
- 判断是否使用
- 这是
处理原型链:
- 为了保证
new fBound()
返回的对象能继承原函数的原型属性,需要进行原型链的连接。- 首先,判断原函数是否有
prototype
,没有就忽略原型链继承。 - 将
fNOP
的原型指向原函数的原型。 - 将
fBound
的原型指向fNOP
的实例。
- 首先,判断原函数是否有
- 为了保证
返回新函数
fBound
:- 将新创建的
fBound
返回,该函数的this
和参数都被绑定了。
- 将新创建的
3. 为什么要使用 fNOP
空函数
如果直接让 fBound.prototype = this.prototype
,会造成原型链的指向问题,当修改 fBound.prototype
时, this.prototype
也会被影响。
例如:
-- -------------------- ---- ------- -------- ------------- --------- - ---- - ------------------------- - ----------- -------------------- - ----- ------------ - ------------------------ ----------------------------- - ----------- ------------------ - ----- - - --- -------------- -------------- -------------------------------- -------------------- ----------------------------- -------------------------
如果使用fNOP
空函数,则只改变了fBound
的原型,不会影响原函数Person
的原型。
-- -------------------- ---- ------- -------- ------------- --------- - ---- - ------------------------- - ----------- -------------------- - ----- ------------ - -------------------------- ----------------------------- - ----------- ------------------ - ----- - - --- -------------- -------------- ----------------------- ----------------------------- -------------------------
4. 兼容 new
调用的情况
当使用 new
关键字调用 bind
返回的函数时, this
应该指向新创建的对象实例。因此需要判断是否使用 new
调用。
5. 核心要点
this
指向的理解:- 普通函数调用:
this
指向调用该函数的对象(在严格模式下,没有对象调用,this
指向undefined
)。 bind
调用:this
指向bind
函数第一个参数。new
调用:this
指向新创建的对象实例。
- 普通函数调用:
- 使用
apply
方法: 用于改变函数执行的this
上下文,并传递参数。 - 原型链继承: 为了保证
new
调用的情况下bind
函数返回的新函数能够继承原函数的原型属性。