This point

In ES5, this always refers to the object that called it last. Let’s look at the simplest example: example 1:

    var name = "windowsName";
    function a() {
        var name = "Cherry";

        console.log(this.name);          // windowsName

        console.log("inner:" + this);    // inner: Window
    }
    a();
    console.log("outer:" + this)         // outer:Window
Copy the code

This always refers to the object that called it last. A () is the last place where a was called; The global object window, which is equivalent to window.a(); Note that we are not using strict mode here. If we use strict mode, the global object is undefined and an error will be reported

Uncaught TypeError: Cannot read property 'name' of undefined.Copy the code

Let’s look at this example again: example 2:

var name = "windowsName";
var a = {
    name: "Cherry",
    fn : function () {
        console.log(this.name);      // Cherry
    }
}
a.fn();
    
Copy the code

In this case, the function fn is called from object A, so the printed value is the value of name in a. Let’s make a small change:

Example 3:

var name = "windowsName";
var a = {
    name: "Cherry",
    fn : function () {
        console.log(this.name);      // Cherry
    }
}
window.a.fn();
Copy the code

The reason Cherry is printed here is because “this always refers to the last object to call it”, and the last object to call it is still object A. Let’s look at this example again:

Example 4:

var name = "windowsName";
var a = {
    // name: "Cherry",
    fn : function () {
        console.log(this.name);      // undefined
    }
}
window.a.fn();
Copy the code

Why would I print undefined here? This is because, as just described, fn is called by object A, that is, fn’s internal this is object A, and object A does not define name, so log’s this.name value is undefined.

This always refers to the object on which fn was last called, because the object on which FN was last called is A. Therefore, even if a does not have the name attribute, it does not continue to look for this.name in the previous object. Here’s another example:

Example 5:

var name = "windowsName";
var a = {
    name : null,
    // name: "Cherry",
    fn : function () {
        console.log(this.name);      // windowsName
    }
}

var f = a.fn;
f();
Copy the code

F () is still called by window because the fn method of a was assigned to f, but it was not called. So this refers to the window.

As we can see from the above five examples, the reference of this is not always determined at creation time. In ES5, this always refers to the object that last called it.

Here’s another example:

Example 6:

var name = "windowsName";

function fn() {
    var name = 'Cherry';
    innerFunction();
    function innerFunction() {
        console.log(this.name);      // windowsName
    }
}
fn()
Copy the code

How do I change the direction of this

I conclude that there are several ways to change the direction of this:

  • Use the arrow function of ES6
  • Use _this = this inside the function
  • Use apply, call, and bind
  • New instantiates an object

Example 7:

var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() },100); }}; a.func2() // this.func1 is not a functionCopy the code

Without the arrow function, an error is reported because the last object to call setTimeout is the window, but there is no func1 function in the window.

We’re going to change this as a demo in this video.

Arrow function

It is well known that the arrow function in ES6 avoids the use of this in ES5. The arrow function’s this always points to this when the function is defined, not when it is executed. If the arrow function is contained by a non-arrow function, then this is bound to the nearest non-arrow function’s this; otherwise, this is undefined.

Example 8:

var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( () => { this.func1() },100); }}; a.func2() // CherryCopy the code

Use _this = this inside the function

If you don’t use ES6, this is probably the easiest way to make sure you don’t make mistakes. We first store the object that calls the function in the _this variable, and then use the _this variable throughout the function so that _this doesn’t change.

Example 9: var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { var _this = this; setTimeout( function() { _this.func1() },100); }}; a.func2() // CherryCopy the code

In this example, in func2, var _this = this; , where this is the object A that calls func2. In order to prevent setTimeout in func2 from being called by window, this in setTimeout is window. We assign this(pointing to variable A) to a variable _this, so that in func2 we use _this to point to object A.

Use apply, call, and bind

You can also change the direction of this using the apply, call, and bind functions. More on this later, but let’s see how this works:

Use the apply

Example 10:

var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.apply(a),100); }}; a.func2() // CherryCopy the code

Use the call

Example 11:

var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.call(a),100); }}; a.func2() // CherryCopy the code

Use the bind

Example 12:

var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.bind(a)(),100); }}; a.func2() // CherryCopy the code

Apply, call, and bind

We’ve already seen that apply, call, and bind can change the direction of this, but these three functions are slightly different. Define apply in MDN as follows;

The apply() method calls a function with a specified this value and arguments supplied as an array (or array-like object)

Grammar:

fun.apply(thisArg, [argsArray])
Copy the code

ThisArg: This value specified when fun is run. Note that the specified this value is not necessarily the true this value when the function is executed. If the function is in non-strict mode, specifying null or undefined automatically points to the global object (window object in browsers) and the original value (number, string, This points to the auto-wrapped object of the original value.

ArgsArray: An array or array-like object whose array elements are passed as separate arguments to fun. If the value of this parameter is null or undefined, no arguments need to be passed in. Array-like objects can be used starting with ECMAScript 5.

The difference between apply and Call is that apply and call are basically similar, except that they take different parameters. The syntax for call is:

fun.call(thisArg[, arg1[, arg2[, ...]]])
Copy the code

So the difference between Apply and call is that the call method accepts a list of arguments, while Apply accepts an array of arguments.

Example 13:

var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; B.a pply (a, [1, 2]) / / 3Copy the code

Example 14:

var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; Biggest all (a, 1, 2) / / 3Copy the code

Let’s try this example out using bind

var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; B.b ind (a, 1, 2)Copy the code

We will find that there is no output. Why is this? Let’s look at the documentation on MDN:

The bind() method creates a new function that, when called, sets its this keyword to the supplied value and, when called, provides a given sequence of arguments before any supply.

Bind creates a new function that we have to call manually:

var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; B.b ind (a, 1, 2) (a) / / 3Copy the code