实现思路:大抵是扭转函数执行环境中 this 的指向,这个 this 的指向依据谁调用了这个函数来决定,如果将这个函数成为某个对象办法,this 就和这个对象进行了绑定。
留神:在自定义的函数中记得返回被调用的函数(this 产生扭转)其返回值,如果传入的对象是 null 或者 undefined,则被调用的函数 this 指向 window。
代码实现:
function Call (Fn,obj,...argument) {
// 如果 obj 是 null 或者 undefined,Fn 的 this 指向 window,所以由 window 来调用
if (obj === undefined || obj === null) {obj = window}
// 1. 给 obj 增加一个属性,值为 Fn,目标是扭转 this 指向
obj.tempFun = Fn
// 2. 调用该函数,扭转执行环境中 this 的指向
let result = obj.tempFun(...argument)
// 3. 删除 obj 增加的办法
delete obj.tempFun
// 4. 返回函数执行的返回值
return result
}
function Apply (Fn,obj,argument) {
// 两者只是传参的模式不同,在函数体里调用自定义的 Call 函数,参数解构赋值即可
return Call(Fn,obj,...argument)
}
function Bind (Fn,obj,...argument) {return function(...argument2) {Call(Fn,obj,...argument,...argument2)
}
}
验证后果:
function fn (a,b) {console.log(a,b,this)
}
let person = {name:'zhangsan',age: 10}
fn(1,2)
Call(fn,person,1,2)
Call(fn,undefined,1,2)
Apply(fn,person,[1,2])
Apply(fn,null,[1,2])
let bindFun = Bind(fn,person)
bindFun(3,4)