[This is the seventh day of my participation in the August More Text Challenge. For details, see: August More Text Challenge]

The first contact with this was in c# and later in JavaScript, and the handling of this is very similar. But JavaScript is a prototype-based programming language with no concept of classes. This means that this will point to the object on which the function is called, usually called the context. Of course this doesn’t stop there; references within a function can be bound to different objects, depending on where the function is called from. This question and variable function promotion are common questions for front end interviews. For more information about variable function promotion, please refer to “Deepening understanding of Javascript Variable Function Declaration Promotion”.

The binding

In JavaScript, Lexical Environments are a normative type used to define associations of identifiers to particular variables and functions based on Lexical nested structures of ECMAScript code. A lexical Environment consists of an Environment Record and a reference to an external lexical Environment that may be empty. In general, lexical environments relate to specific syntactic structures of ECMAScript code. Code such as a function declaration, a block statement, a catch in a try statement, etc., generates a new lexical environment after each operation.

Execution Contexts is a specification device for tracking runtime evaluation of code via the ECMAScript compiler. Each agent has at most one execution context in which the code is executing at any one time.

Each execution context contains an Environment Record to which variable and function names are added as the JavaScript engine executes code. This is the basic concept of binding. Helps associate identifiers (variables, function names) with the this keyword of the execution context.

A function call

This is simple. This refers to the source of the call, and this in a function refers to the global object.

function callAuthor() {
    console.log(this.author);
}

callAuthor(); // undefined

var author = "DevPoint";

callAuthor(); // DevPoint
Copy the code

In strict mode, the value of this.author is undefined.

let & const

If variables are declared with let or const at the global level, they are not stored in the global object. In contrast, in a declarative environment record that is not accessible, so the previous example outputs different results when const is used.

function callAuthor() {
    console.log(this.author);
}

const author = "DevPoint";
callAuthor(); // undefined
window.author = "DevPoint";
callAuthor(); // DevPoint
Copy the code

Implicit binding

When a function references a context object, the implicit binding rule binds this in the function to that context object. Only the previous or last level in the chain of object property references plays a role in the call.

const thisArticle = { title: "JavaScript", printTitle: function () { console.log(this.title); }}; thisArticle.printTitle(); // JavaScriptCopy the code

If the object contains only a reference to the printTitle call function, the same result can be obtained:

function printTitle() {
    console.log(this.title);
}

const thisArticle = {
    title: "JavaScript",
    printTitle: printTitle,
};

thisArticle.printTitle(); // JavaScript
Copy the code

Explicitly bound

Binding an object to this via the call, apply, or bind methods is called explicit binding.

function article() {
    console.log(this.title);
}

const thisArticle = {
    title: "JavaScript",
};

article.call(thisArticle); // JavaScript
Copy the code

Both Call and apply perform the same operation, and the first argument for both should be what this points to. The difference occurs if additional arguments need to be passed to the function being called.

  • usecallIs passed as an argument list separated by commas
  • useapplyIs passed as an array
  • usebindA new function is created and permanently bound tothis

Create a new function that permanently binds this to thisArticle and reassign article to the new permanent binding function:

function article() {
    console.log(this.title);
}

const thisArticle = {
    title: "JavaScript",
};

const newArticle = article.bind(thisArticle);
newArticle(); // JavaScript
Copy the code

The new binding

The new keyword constructs a new object to which this refers. When a function is called as a constructor using the new keyword, this refers to the new object that is created.

function Article(title) {
    this.title = title;
}

const thisArticle = new Article("JavaScript");

console.log(thisArticle.title); // JavaScript
Copy the code

Arrow function

Using the arrow function, this remains the same value as its parent scope. For example, the value of this in the arrow function is the same as the value of this in the outer Article function:

function Article(title) {
    this.title = title;
    this.toUpper = () => {
        return this.title.toUpperCase();
    };
}

const thisArticle = new Article("JavaScript");

console.log(thisArticle.title); // JavaScript

console.log(thisArticle.toUpper()); // JAVASCRIPT
Copy the code

conclusion

In JavaScript, this is a container-bug-causing keyword. In order to reduce such problems, you need to understand more about this. From the introduction above, the best practice is to use arrow functions whenever possible.