This has always been a platitude in JS, but how do we understand it? In JavaScript Advanced Programming, this is explained as:

The this object is bound at run time based on the execution environment of the function.

Let’s read it word for word:

  • This is an object
  • The creation of this is related to functions
  • This is bound to the execution environment

In layman’s terms, “This is whoever called this function.”


This in a direct function call

Here’s an example:

var x = 1;

function testThis() {
    console.log(this.x);
}

testThis();  / / 1Copy the code

Js has a global object window. Calling testThis directly is equivalent to calling the testThis method under the window. Variables directly declared are also mounted under the window object.

var x = 1;
function testThis() {
    this.innerX = 10;
    return 1;
}
testThis() === window.testThis();  // true
innerX === window.innerX;  // true
x === window.x;  // trueCopy the code

Similarly, using this in an anonymous function is also a window to point to, because the execution environment of an anonymous function is global.

(function () {
    console.log(this); //window}) ();Copy the code

However, there are exceptions to everything, and the exception to JS is strict mode. In strict mode, the this keyword is disallowed from pointing to global objects.

(function () {
    'use strict';
    console.log(this); //undefined}) ();Copy the code

This in object method calls

Here’s another chestnut:

var person = {
    "name": "shenfq"."showName": function () {
        console.log(this.name); }}; person.showName();// 'shenfq'Copy the code

In this case, this in the showName method refers to the object Person, because showName is called on the person object, so this.name in the showName method is actually person.name.

But if we think differently, we assign the showName method to a global variable and call it in the global environment.

var name = 'global',
    person = {
        "name": "shenfq"."showName": function () {
            console.log(this.name);
        } 
    },
    showGlobalName = person.showName;
showGlobalName(); // 'global'Copy the code

As you can see, when the showName method is called in the global environment, this points to the window.

Another way to think about it, what if the showName method is called by another object?

var person = {
        "name": "shenfq"."showName": function () {
            console.log(this.name);
        } 
    },
    animal = {
        "name": "dog"."showName": person.showName
    };

animal.showName(); // 'dog'Copy the code

Now the name becomes the name of the animal object, and a little bit more complicated, if you’re calling a method on a property of the object, and that property is another object.

function showName () {
    console.log(this.name);
}
var person = {
    "name": "shenfq"."bodyParts": {
        "name": "hand"."showName": showName
    },
    "showName": showName
};

person.showName(); // 'shenfq'
person.bodyParts.showName(); // 'hand'Copy the code

Although the showName method is called from the Person object, bodyParts under Person is ultimately called, so it doesn’t matter which object the method is written under. What matters is who finally called the method. This always refers to the object that finally called it. In general, this is just what it is. You can tell where this points by knowing the context in which the function body is executed. This rule applies in most cases.

One last thought, when a method returns an anonymous function, where does this refer to in that anonymous function?

var name = 'global',
    person = {
        "name": "shenfq"."returnShowName": function () {
            return function () {
                console.log(this.name); }}}; person.returnShowName()();// 'global'Copy the code

The answer is clear: wherever an anonymous function is written, whenever it is called directly, its this refers to window, because the execution environment of an anonymous function is global.


This in the new constructor

Here’s an example:

function Person (name) {
    this.name = name;
}
var global = Peson('global'),
    xiaoming = new Person('xiaoming');

console.log(window.name); // 'global'
console.log(xiaoming.name); // 'xiaoming'Copy the code

Instead of using the new operator, call the Person function directly, where this still points to the window. When the new operator is used, the function is called a constructor.

A constructor is a function used to construct an object. Constructors always appear with the new operator, and in the absence of the new operator, the function is indistinguishable from normal functions.

The process of performing a new operation on a constructor is called instantiation. The new operation returns an instantiated object, and this in the constructor points to that instantiated object, such as Xiaoming in the example above.

There are a few things to note about constructors:

  1. By default, the instantiated object has a constructor attribute pointing to the constructor;

function Person (name) {
    this.name = name;
}
var xiaoming = new Person('xiaoming');

console.log(xiaoming.constructor); // PersonCopy the code
  1. The instantiated object inherits the constructor’s prototype and can call all the methods on the constructor’s prototype.

function Person (name) {
    this.name = name;
}
Person.prototype = {
    showName: function () {
        console.log(this.name); }};var xiaoming = new Person('xiaoming');

xiaoming.showName(); // 'xiaoming'Copy the code
  1. If the constructor returns an object, the instance object is the object returned, and all attributes assigned by this will not exist

function Person (name, age) {
    this.name = name;
    this.age  = age;
    return {
        name: 'innerName'
    };
}
Person.prototype = {
    showName: function () {
        console.log(this.name); }};var xiaoming = new Person('xiaoming'.18);

console.log(xiaoming); // {name: 'innerName'}Copy the code

This when a function is called indirectly by call or apply

Here’s another example:

var obj = {
    "name": "object"
}

function test () {
    console.log(this.name);
}

test.call(obj);   // 'object'
test.apply(obj);  // 'object'Copy the code

The Call and apply methods are both methods mounted under the Function prototype, and all functions can be used.

There are similarities and differences between the two functions:

  • The same thing is that their first argument is bound to this in the function body. If no argument is passed, this is bound to the window by default.
  • The difference is that the subsequent arguments to call are passed to the calling function as arguments, whereas the second argument to apply is an array whose elements are the arguments to the calling function.

The language was so pale that I had to write a code:

var person = {
    "name": "shenfq"
};
function changeJob(company, work) {
    this.company = company;
    this.work    = work;
};

changeJob.call(person, 'NASA'.'spaceman');
console.log(person.work); // 'spaceman'

changeJob.apply(person, ['Temple'.'monk']);
console.log(person.work); // 'monk'Copy the code

It is worth noting that these two methods convert the parameters passed into object types, regardless of whether they are strings or numbers.

var number = 1, string = 'string';
function getThisType () {
    console.log(typeof this);
}

getThisType.call(number); //object
getThisType.apply(string); //objectCopy the code

Change the function’s this pointer by using bind

One last chestnut:

var name = 'global',
    person = {
        "name": "shenfq"
    };
function test () {
    console.log(this.name);
}

test(); // global

var newTest = test.bind(person);
newTest(); // shenfqCopy the code

The bind method is new in ES5. It is a Function prototype like call and apply, so each Function can be called directly. The bind method returns the same function as the calling function, except that this is permanently bound as the first argument to bind, and functions bound by bind cannot be rebound.

function showName () {
    console.log(this.name);
}
var person = {"name": "shenfq"},
    animal = {"name": "dog"};

var showPersonName = showName.bind(person),
    showAnimalName = showPersonName.bind(animal);

showPersonName(); //'shenfq'
showAnimalName(); //'shenfq'Copy the code

The showPersonName method binds the Person object to showName and then rebinds the Animal object to showPersonName.

This in the arrow function

Really the last chestnut:

var person = {
    "name": "shenfq"."returnArrow": function () {
        return (a)= > {
            console.log(this.name); }}}; person.returnArrow()();// 'shenfq'Copy the code

Arrow function is a new syntactic sugar in ES6. Simply speaking, it is the shorthand of anonymous function, but different from anonymous function, this in arrow function represents the outer execution context, that is to say, this of arrow function is this of outer function.

var person = {
    "name": "shenfq"."returnArrow": function () {
        let that = this;
        return (a)= > {
            console.log(this== that); }}}; person.returnArrow()();// trueCopy the code

Supplement:

This in the event handler:

var $btn = document.getElementById('btn');
function showThis () {
    console.log(this);
}
$btn.addEventListener('click', showThis, false);Copy the code

Click the button to see the console print out the element node.

The outcome

By default, this in the event function is the element to which the event is bound

$btn.showThis()

As long as the button is clicked, the event function is fired in this way, so the this in the event function represents the element node, which also conforms to the definition of “this is whoever called this function”.

This in eval:

eval('console.log(this)'); //window
var obj = {
    name: 'object'.showThis: function () {
        eval('console.log(this)');
    }
}
obj.showThis(); // objCopy the code

Eval is a function that executes JS code on the fly, treating a string passed into it as js code. This method is usually used sparingly, because it’s dangerous. Think of dynamically executing code, which can execute any string, but it can also be very convenient if used well.

This in eval is similar to the arrow function, and is the same as this in the outer function.

Of course, this is only for modern browsers, and on older browsers, such as IE7 and WebKit, eval’s This point will be slightly different.

Eval can also be used to get global objects (window, global) in special cases, using (1,eval)(‘this’).


So let me do that, and I’ll add ^ _ ^ if I need to

Reference:

  1. this – JavaScript | MDN
  2. Javascript’s this usage
  3. (1,eval)(‘this’) vs eval(‘this’) in JavaScript?

The original link