Love the homeland, the beginning of the heart is to set foot on the hometown of the black soil of the moment, home — salute the most lovely people

This article uses JavaScript you Don’t Know (Volume 1) as a reference to claim that I can already afford paper books. (Respect knowledge)

Do you really understand this? Looking at this, is it familiar and strange? This article can help me learn and also lead you to learn something? (Remember, don’t believe in a few days’ quick learning, one article can be learned directly, feel it with your heart, and march forward with the fiery heart of learning.)

Why do we say that one of the most complex mechanics in javaScript is that? Personally, I think its direction is multiple transformation, and sun Wukong 72 changes, you do not know which is sun Wukong become, so also practice a pair of fire eyes.

This is essentially what makes your code elegant and allows you to quickly get the context you want.

What on earth is this?

The binding of this has nothing to do with where the function is declared, except how the function is called. (P80)

Before we look at the binding process of this, we need to know the call location, we need to analyze the call stack, call location;

        // Where the function is defined
        function wenshu(){
        // Call stack is a sequence of functions called.
            // call stack wenshu
            // Call location
            light()
            console.log('76wenhsu')}function light(){
            // call stack wenshu -> light
            console.log('Fire in heart, light in eye:' Wu ')}// The call location is where the function is executed
        // Call location
        wenshu()
Copy the code

The default binding

Function call type “Independent function call. Think of it as a default rule where no other rules can be applied.

This is the simplest way to bind this, with the following code:

        //const a = '76wenshu';
        var  a = '76wenshu';
        function wenshu(){
            debugger
            // call stack wenshu
            var a = 'Fire in the heart, light in the eye'
            // Call location
            light() // => this.light()
            console.log(this)
            // Const and let declared variables are not in window.
            console.log(this.a)// undefined when a is declared const
            //var = '76wenshu'
            debugger
        }
        function light(){
            // call stack wenshu -> light
            console.log(this.a)// Why not call wenshu (a) as above
        }
        // Call location
        wenshu()
Copy the code

Const, let declared variable not found under global object window.

Implicit binding

        function light(){
           
           console.log(this.a)
       }
       var obj ={
           a:2.light:light
       }
       light();//undefined
       obj.light()/ / 2
Copy the code

Personally, when you assign a function to a variable, you assign the body of the function to the variable so that it can be used

Multi-layer call:

        function light(){
          
           console.log(this.a)
       }
       // The order in which objects are declared is different to prevent the problem of variable promotion.
       var obj1 ={
           a:76.light:light
       }
       var obj ={
           a:2.obj1:obj1,
           light:light
       }
      
       console.log(obj);
       obj.light();/ / 2
       obj.obj1.light();/ / 76
Copy the code

Personally think: get the first month (nearby principle)

  1. Implicit loss
        function light(){

           console.log(this.a)
       }
       
       var obj ={
           a:2.light:light
       }
      var a = 'six';
      var bar = obj.light
      bar();/ / six
Copy the code

Is it a little bit different when you call bar why is this happening, how does it refer directly to the global variable A that; I think of functions as objects that can only be referred to, and they are a process of copying again

    var bar = obj.light
    =>
    var bar = function(){
        console.log(this.a)
   }
Copy the code

More deceptively, functions use functions as arguments:

        function light(){
           
           console.log(this.a)
       }
       var obj ={
           a:2.// obj1:obj1,
           light:light
       }
       function bar(fn){
           console.log(fn);
           fn()
       }
      var a = 'six';
       bar(obj.light);/ / six
       // If the function is an arrow function, there is a distinction, which will be explained later
       setTimeout(obj.light, 100);/ / six
Copy the code

Conclusion: Implicit loss of the reason, the function call conforms to the rules of use, equivalent to using a function, the original function is replaced.

Explicitly bound

Display binding has to say call/apply/bind three functions

        // How is call implemented
       function call(content=window.arguments){
           //const content = content || window;
           arguments=arguments?arguments: [];// I don't think it is necessary to write like this
           //const fn = Symbol()
           content.fn=this;
           constresult =content.fn(... arguments)delete content.fn
           return result
       }
Copy the code

Here I say:

Many people tell you to write the call source code, but can you really remember?

Do you understand? Write as much as you can remember don’t copy code, don’t copy code, don’t memorize it know it, understand it, you can see why you’re writing the call function. (Remember not to fake learning, touching yourself, there is no sense in that)

Everyone has a set of their own learning methods, as early as possible to find him understand it, to take less detours in learning. I just took a lot of detours on my own. So I’m trying to build a front-end self-learning network.

Nonsense not to say, the following to say it train of thought:

Q: What is the problem that Call is trying to solve? What does it do?

A: I understand that call is used to change the reference of this in a function, so that you can get this to refer to the object you want.

Return obj (which object you want to point to).fn (which function you want to use) (arguments) (which arguments you want to pass in).

Now that you know what you want, it’s up to you to implement it. That is, call passes in two parameters (content (the object you want to point to),… Arguments (arguments you want to pass in)), don’t bother to understand it at all,

After passing in two arguments, then you can bind the function fn that you want to use to the object that you want to use that obj.fn way is fine, so let’s go to the function

const content = content 
//func.call()
// This refers to func
content.fn =this;
return content.fn();
Copy the code

The body of the function is done so we’re going to have to fix it, because it’s pretty crude, you know, if you look at the binding situation; Suddenly feel forgot to pass what ha ha, forgot to pass parameters…

const content = content
// Don't forget
cosnt argus = arguments
//func.call()
// This refers to func
content.fn =this;
return content.fn(argus);
Copy the code

The whole idea of applying is the same as that of passing parameters.

I think it’s exactly the same, if I don’t want to say the difference it’s the difference in parameters. If the number of arguments is small and the order of arguments is fixed, call is used; if the order of arguments is opposite, apply is used. If the argument is an array, just use Apply

What’s the difference between call and apply? Call and apply return the result of calling a function and bind is the result of calling a function, and you have to call it again if you need to,

vara= fn.call(obj,... args)// Get the desired value directly

varb = fn.bind(obj,.. args);// Return a function instead of the result
b()// Return the result;
Copy the code

// Based on this difference, we can modify the existing call and apply functions

        function bind(content=window. arges){
            const fn = thisarges=arges? arges:[];return function newFn(. newArges){
            // Why is this judgment made later, Mark
                if(fn instanceof newFn){
                    return newfn(... arges,... newArges) }return fn.apply(content,[...arges,...newArges])

            }
        }
Copy the code

Call /apply/bind: call/apply/bind

        function light(){
            console.log(this.a)
        }
      
        var obj ={
            a:2,}// Force the light function to bind to the obj object
        light.call(obj)/ / 2
Copy the code

// Explicitly bind call/apply

        function light(){
            console.log(this.a)
        }
       
        var obj ={
            a:2.light:light
        }
        var bar =obj.ligh.call(obj)Display binding does not solve the problem of implicit loss
        bar()/ / an error
Copy the code

// Hard bind currified

        function light(){
            // call stack wenshu -> light
            console.log(this.a)
        }
        var obj ={
            a:2.light:light
        }
        //var bar =function(){
            //light.call(obj)
        / /}
        // This cannot be modified after hard binding
        var bind = obj.light.bind(obj);
        bar()
Copy the code

For API call contexts such as forEach, the second argument is the this pointer inside the function.

The new binding

function light(a){
    this.a = a
}
var bar = new light(2)
console.log(bae.a)/ / 2
Copy the code

// construct a new object and bind it to light(); On the this call, become the new binding

priority

When more than one rule can be used at a call location, there will always be order, high weight and low weight.

The default binding is definitely the least weighted here. Let’s look at implicit binding and explicit binding.

        // Implicitly bind and show the priority of the bind
        function dq(){
            console.log(this.a)
        }
        var obj={
            a:'76 documents'.dq:dq
        }
        var obj1={
            a:'Fire in the heart, light in the eye'.dq:dq
        }
        obj.dq();
        obj1.dq();
        
        obj.dq.call(obj1);
        obj1.dq.call(obj);
Copy the code

Use the code above to determine explicit binding > implicit binding

Implicit binding or new binding, which is higher?

        function dq(params){
            this.a = params;
            // console.log(this.a)
        }
        var obj={
            a:'76 documents'.dq:dq
        }
        obj.dq(3);
        console.log(obj.a);

        var bar = new obj.dq('Fire in the heart, light in the eye')
        console.log(obj.a)
        // There is no relationship between the new binding and the implicitly bound object
        console.log(bar.a)

Copy the code

Judging from the code above

New Binding > Implicit binding

Remember new Bind > Show bind and we’ll talk about that later

To determine this

This can be determined by new> explicit > implicit > default

Bugs Endless bugs This is ignored.

        function dq(){
            console.log(this.a)
        }
        var obj={
            a:'76 documents'.dq:dq
        }
        var a = 2;
        var ø = Object.create(null);
        // Using NULL may lead to more bugs than ever before
        dq.call(null);// This will be ignored by default
        dq.call(obj);
        //ø is nullDq. Call (ø);// Do not ignore this, just point to more empty
Copy the code

Indirect reference

I don’t think I’ve seen a function used this way, I think it’s theoretical;

        function dq(){
            console.log(this.a)
        }
        var a = 2;
        var o = {a:3.foo:foo};
        var p = {a:4};
        o.dq();/ / 3
        // I think a normal person would write this... ", test yourself or test the students who took over later, easy to read, easy to use is good, not the problem of other people's technical dishes, is that you write the code is clean, can read, write the code in addition to their own others can not understand what the practical significance of that.
        (p.dq = o.dq)()/ / 2
Copy the code

Soft binding

In order to make the binding more flexible, there is enough to point to other objects: the book of soft binding code

if(!Function.prototype.softBind){
    Function.prototype.softBind = function(obj){
        const fn = this;
        var curried = [].slice.call(arguments.1);
        var bound = function(){
            return fn.apply({
                (!this || this= = = (window || global))? obj:this,
                curried.concat.apply(curried,arguments)})}; bound.prototype =Object.create(fn.prototype);
        returnbound; }}` ``javaScript function foo(){ console.log(`name:${this.name}`) } var obj = {name:'obj'},obj2={name:'obj2'},obj3={name:'obj3'}; var fooOBJ = foo.softBind(obj); fooOBJ(); //name:obj obj2.foo = foo.softBind(obj); obj2.foo() //name:obj2 fooOBJ.call(obj3); SetTimeOut (obj2.foo, 10) //name:objCopy the code

*** arrow function ***

To sum up:

In any case, the arrow function’s this is the same as the outer function’s this. If the outer function’s this is not function, the window will be suffocated.

        function foo(){
            setTimeout(() = >{
                // This is morphologically inherited from foo()
                console.log(this.a)
            },100);
        }
        var obj = {
            a:2
        }
        foo.call(obj); / / 2
Copy the code

self = this;

        function foo(){
            var self = this;
            setTimeout(function(){
                console.log(self.a);
            },100)}var obj = {
            a:2
        }
        foo.call(obj); / / 2
Copy the code

Surprising questions:

The arrow function in this is undefined, the debugger sees, does not affect normal use of printing consoel.log(this);

This is due to chrome debugger optimizations. If a local variable (equivalent to a block-level scope) is not referenced inside a function (in this case, this), it is not stored in the function context object.

The result is that the arrow function this, the existence of the event is the same as the function closed local variable, are not shown reference output is undefined

{
console.log(a)
var a=2
}
Copy the code

Thank you for this:

JavaScript you Don’t Know (Volume 1) by KYLE SIMPOSON. Translated by Zhao Wangye and Liang Jie.