First, we will specify four binding rules for this:

1. Default binding

When called independently, this refers to the global object. If strict mode is used, the default binding cannot be used for the global object. This is bound to undefined and is thrown (TypeError: this is undefined).

2. Implicit binding

When a function is added to an object as a reference property, the implicit binding rule binds this from the function call to the context object

3. Display the binding

Using the Apply call method, bind this to a function when it is called, specifying the value of this for the called function

4. The new binding

This is the this binding when using the new operator

The four rules have ascending priorities from top to bottom.

Second, the bind function has three function points:

1. Change the this pointer to the original function, i.e. the binding context, and return a copy of the original function

2. When a bind function is called, additional arguments to bind are passed to the bound method before arguments.

3. Note that a binding function can also use the new operator to create an object. This behavior is like using the original function as a constructor. The new operator modifies this to a higher priority.

/ / in the Function prototype is defined on this method takes the context object as the first parameter to the Function. The prototype. Mybind =function(context){// Determine whether it is a function typeif(typeOf this! = ='function')return false;
    let_self=this; // Get parameters other than the first contextletarg=[...arguments].slice(1); // Define a new function that uses the apply or call methods to change its this reference to contextlet fn=function(){// Arguments arebindReturn the argument to the function, concatenated with the argument above to complete the argumentletArg2 = arg. Concat (the arguments [...]) / / whenbindWhen I encounter new,bind// We need to check whether the prototype chain has fn to determine if new is encounteredif(this instanceof fn){
            return _self.apply(_self,arg2)
        }else{
            return_self. Apply (context,arg2)}} // Change the prototype of the return function to the prototype of the binding function. The instance can inherit the value of the binding function's prototypereturn 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,'your sister')
 ffa1('100') / /'fooValue'This points to foo //'your sister'
 //'100'// After encountering newlet gg=new ffa1('gg your sister') console.log(gg.friend) //undefined because this refers to gg,gg has no value'your sister'
//'gg your sister'
//'李磊'
Copy the code