手写bind实际上就是考验对柯里化和new的理解,所以首先要搞明白bind会不会对构造函数有影响
function person(name) {
this.name = name
console.log(this.age);
}
const son = {
age: '18'
}
const abc = person.myBind(son, 'hello')
abc() // 18
const b = new abc('wumao') // log打印undefined
console.log(b);//{ name: 'hello' } //说明bind在this不起作用,但是参数上还是起作用的
从以上结果来看bind不影响new过程中this的指向(new一个函数的时候,如果返回的是复杂数据类型,则返回这个复杂数据类型,如果是简单数据类型,则返回这个简单数据类型的包装对象,并且它的原型会继承该构造函数的原型)
这时候我们开始写代码
Function.prototype.myBind = function (obj, ...args) {
//首先存储一下要绑定的函数
const fn = this
//因为肯定不止一个参数,所以这里需要柯里化返回另外一个函数
const returnFn = function (...secondArgs) {
// 这里面判断是否使用了new(this指向实例化对象,通过instanceof返回的构造函数是否为true)
const isNew = this instanceof returnFn
// 如果使用的是构造函数,则是实例对象,否则是这个被绑定的对象
const thisObj = isNew ? this : Object(obj)
// 用call绑定this,并且传递参数
return fn.call(thisObj, ...args, ...secondArgs)
}
//复制调用函数的prototype给返回的函数
returnFn.prototype = Object.create(fn.prototype);
return returnFn
}