首先先明确四种this的绑定规则:
1.默认绑定
独立函数调用时, this 指向全局对象,如果使用严格模式,那么全局对象无法使用默认绑定, this 绑定至 undefined 并抛错(TypeError: this is undefined)
2.隐式绑定
当函数作为引用属性被添加到对象中,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象
3.显示绑定
运用apply call 方法,在调用函数时候绑定this,也就是指定调用的函数的this值
4.new绑定
就是使用new操作符的时候的this绑定
上述四条规则优先级由上到下依次递增。
其次bind函数有三个功能点:
1.改变原函数的 this 指向,即绑定上下文,返回原函数的拷贝
2.当 绑定函数 被调用时,bind的额外参数将置于实参之前传递给被绑定的方法。
3.注意,一个 绑定函数 也能使用 new 操作符创建对象,这种行为就像把原函数当成构造器,thisArg 参数无效。也就是 new 操作符修改 this 指向的优先级更高。
//在Function的原型上定义这个方法 接受上下文对象作为第一个参数
Function.prototype.mybind=function(context){
// 判断是否为函数类型 不是直接终止
if(typeOf this!=='function')return false;
let _self=this;
//获取除第一位context的其他参数
let arg=[...arguments].slice(1);
//定义一个新的函数 用apply或call方法改变其this指向为context
let fn=function(){
//这里的arguments是bind返回函数的参数,将他和上面的参数拼接到一起才是完整的参数
let arg2=arg.concat([...arguments])
//当bind遇到new时,bind 时指定的 this 值会失效,但传入的参数依然生效
//需要通过查阅原型链是否有fn的方法判断遇到new
if(this instanceof fn){
return _self.apply(_self,arg2)
}else{
return _self.apply(context,arg2)
}
}
// 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承绑定函数的原型中的值
fn.prototype=_self.prototype
return fn
}
let foo={value:'fooValue'}
function fa1(name,age){
console.log(this.value)
console.log(name,age)
}
fa1.prototype.friend='李磊'
let ffa1=fa1.mybind(foo,'你妹')
ffa1('100')
//'fooValue' this指向foo
//'你妹'
//'100'
//遇到new之后
let gg=new ffa1('gg你妹')
console.log(gg.friend)
//undefined 因为this指向gg,gg下无value
//'你妹'
//'gg你妹'
//'李磊'