手写实现bind函数

1,846 阅读2分钟

首先先明确四种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你妹'
//'李磊'