Today, a friend sent me a question and asked me to help explain it.

When I see the topic, the first glance feel thief simple, but see questions to the back more meng force, in pondering can guess …………

var age = 10;

var person={

   age:20.

   getAge(){

       var age = 30;

       return this.age;

    },

};

alert(age,age*2);



person.getAge(); 



var b = person.getAge;

b(); 



(person.getAge)(); 



(1,person.getAge)();



(1,person.getAge.bind(person))();



(person.getAge,person.getAge)();



(person.getAge=person.getAge)();



person.getAge.call(); 



person.getAge.call(person);



function getAge2({

    this.age = 40;

    console.log(person.getAge());

};

getAge2();

console.log(age);



function getAge3(){

    this.age = 50;

    this.getAge4 = (a)= >{

        console.log(person.getAge.call(this));

    }

}

new getAge3().getAge4();

console.log(age);



function getAge4(){

    this.age = 60;

    this.getAge5 = (a)= >{

    console.log(person.getAge.call(this));

    }

}

new getAge4().getAge5();

console.log(age);



var age2 = 10;

var person2={

   age2:20.

   getAge2:(a)= >{

       var age2 = 30;

       return this.age2;    

    },

};

console.log(person2.getAge2.call());

console.log(person2.getAge2.call(person2));

Copy the code

Sure enough, I got a lot wrong…

This topic, the topic of simple could not be more simple, is the object, function, variable, but ask deep, without solid knowledge, it is difficult to answer these questions.

To answer these questions, it’s important to know more about this and comma expressions.

Let’s start with a quick review of these two very important things. Finally, look at the comprehensive topic at the end of the article.

this

This is very important in JS. In the written examination, if there is a survey of basic knowledge, then the probability of “This” is not generally high.

Common function

In a word: the caller points to the caller.

var person={

   age:20.

   getAge(){

       var age = 30;

       return this.age;

    },

};

person.getAge(); / / 20

Copy the code

This getAge method is called by person, so this points to person, and the output of person.age is 20;

Arrow function

In a word: the caller points to whomever he points.

var age = 10;

var person={

   age:20.

   getAge:(a)= >{

       var age = 30;

       return this.age;

    },

};

person.getAge(); / / 10

Copy the code

The getAge method is called by a person, so the getAge method is the same as the getAge method called by a window. So getAge also points to window and prints 10.

Force change this to point

In a word: point to whomever you say.

There are call, apply, and bind methods for changing this.

var age = 10;

var person={

   age:20.

   getAge:function(){

       var age = 30;

       return this.age;

    },

};

person.getAge.call(person);

Copy the code

So when we do getAge, we pass in a person, so getAge this points to person, so we print 20.

Comma expression

Comma Operator

(http://www.ecma-international.org/ecma-262/#sec-abstract-operations)

Comma expressions can be used to split any expression, function arguments, and so on.

function test(){

    let a=1;

    return ++a,a++,a++;

}

console.log(test());

Copy the code

Here the comma is used to split the expression, equivalent to:

function test(){

    let a=1;

    ++a;

    a++;

    return a++;

}

console.log(test());

Copy the code

Return (a++); return (a++); return (a++);

Look at the original problem

Now let’s answer the above questions one by one, and I’ll post some more questions.

var age = 10;

var person={

   age:20.

   getAge(){

       var age = 30;

       return this.age;

    },

};

Copy the code

alert(age,age*2)

Here, the comma separates the Argument Lists, because alert only accepts one Argument, the first one, and ignores the rest. So the popover is 10.

var b = person.getAge; b();

The output is 10, mainly to distinguish person.getage (), which is currently assigned to a variable b and then executed to b().

Is equivalent to:

var b = person.getAge; 

window.b(); 

Copy the code

Back to the previous point, which is called, to whom. Here, after the assignment, the call to b is window, so this refers to window, and the answer is 10.

(person.getAge)();

The parentheses are just a partition and have no real meaning, equivalent to person.getage (). So the answer is 20;

(1,person.getAge)();

The difference between this and the last problem is that we introduced a comma expression. We know that the comma expression returns the last value, person.getage, and notice that this is the expression return value.

Is equivalent to:

var a = (1,person.getAge);

a();

Copy the code

Or:

var a = (false||person.getAge);

a();

Copy the code

Obviously, the caller to A is window, so the answer is 10. Notice that this is in non-strict mode.

If this is null or undefined, it will refer to window. If this is undefined, it will refer to window. In non-strict mode it will point to Window, and in strict mode it will remain null or undefined.

"use strict"

var age = 10;

var person={

   age:20.

   getAge(){

       var age = 30;

       return this.age;

    },

};

console.log(person.getAge());// The output is still 20, and the this pointer points to person

var a = (1,person.getAge);

a();// Cannot read property 'age' of undefined, this is undefined

Copy the code

(1,person.getAge.bind(person))();

Bind the comma expressions and bind the dots.

varA = (1,person.getAge.bind(person));

a();

Copy the code

Bind (person); bind (person);

person.getAge.bind(person)()

Copy the code

The answer is 20. This points to person.

(person.getAge,person.getAge)();

This is essentially a comma expression that returns the value of the last item, and it’s just a trick to set two person.getAge in a row. The previous Person. getAge doesn’t matter. Insist that qingshan mountain does not relax, firmly eliminate traps.

Is equivalent to:

(1,person.getAge)();

Copy the code

The answer is the same as above, 10.

(person.getAge=person.getAge)();

This is a bit different: the object person is given a getAge property (if it has a getAge property, it is reassigned), and the getAge property is assigned as person.getAge.

Inside the parentheses is an assignment expression whose return value is the getAge property of the person object to which the person. GetAge has been reassigned.

Is equivalent to:

var person.getAge = person.getAge / / assignment

var a = person.getAge;  // The expression returns a value

a();

Copy the code

As explained above, the output is 10.

person.getAge.call(); person.getAge.call(person);

Here we use the call function to change the this pointer. When no scope parameter is passed, this is undefined in strict mode, which is non-strict mode.

Call, apply, and bind can all change the this pointer as follows:

// 10 call is null, this is undefined, and is redirected to window

person.getAge.call();

// 20 This pointer points to person

person.getAge.call(person); 

Copy the code

At the end of the big questions

Title 1

function getAge2({

    this.age = 40;

    console.log(person.getAge());/ / 20

};

getAge2();

console.log(age);/ / 40

Copy the code

The person.getAge inside is still who called who, and the this of the Person. getAge method is pointing to Person, and the output is 20. But there is an assignment of this.age = 40.

So what is this? And of course who calls who, so getAge2 is the window call, so this is the window call.

So the age of the outer layer has been changed to 40, so console.log(age) has been changed to 40.

Topic 2

function getAge3(){

    this.age = 50;

    this.getAge4 = (a)= >{

        console.log(person.getAge.call(this));/ / 50

    }

}

new getAge3().getAge4();

console.log(age); / / 40

Copy the code

In getAge3, a public method getAge4 is defined, but this is an arrow function that uses the call function Person. getAge to change the this pointer to the current this.

It still depends on who called getAge4, in this case it’s new getAge3(). This instance calls getAge4, so this in call refers to new getAge3(). Here this.age=50 is set to 50, So the output is 50.

However, the global age is not changed. Unlike in question 1, where this refers to the instance object, not the window, the global age is still 40.

Question 3

By the time you’ve read this, you’ve probably been enlightened and understood. Can you do this?

var age2 = 10;

var person2={

   age2:20.

   getAge2:(a)= >{

       var age2 = 30;

       return this.age2;

    },

};

console.log(person2.getAge2.call()); / / 10

console.log(person2.getAge2.call(person2)); / / 10

Copy the code

The key difference here is that the getAge2 function uses the arrow function. As understood above, the arrow function this points to person2, right?

Wrong! Not so.

The arrow function does not have its own this, so how can call change its own this pointer?

With reference to the document: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

So neither call() nor call(person2) above can modify the this pointer, so both output a global 10.

End

Let’s do one more problem, the this of the arrow function.

var age = 10;

var person={

   age:20.

   child: {

    age:40.

    getAge:function(){

       return this.age;

    },

   },

   child2: {

    age:40.

    getAge:(a)= >{

       return this.age;

    },

   },

   child3:function(){

    this.getAge = (a)= >{

        return this.age;

    }

   }

};

console.log(person.child.getAge());/ / 40

console.log(person.child2.getAge()); / / 10

console.log((new person.child3()).getAge()); // undfined

Copy the code

From what we’ve seen above, we know that person.child.getage () ‘s this is who calls to whom, this is child call, so it points to child, and outputs 40.

We know that the arrow function does not have its own this, so what is its this?

That is, the current arrow function goes up and finds this of the function’s scope, which is the this of the current arrow function.

So, the parent caller of the person.child2.getAge function is child2, but child2 is an object, and it doesn’t have its own this and scope, so I look up person, and I find that person is also an object, and I look up again, The window Boss is found, so this points to window and the output is 10.

(new Person.child3 ()).getage (). This is an instance of new Person.child3 (). However, child3 instance does not have an age attribute, so it outputs undefined.

These questions are really difficult! If you do not understand, read a few answers, I believe you will suddenly see the light! Or pay attention to the public number, plus the author’s wechat, one to one answers.

Welcome to pay attention to my wechat public number, do together reliable front end!