At present, the front-end is generally developed by using frameworks such as React and VUE, but it often ignores the basic knowledge of JavaScript. Whether the foundation is solid or not is a very important indicator to measure the level of development technology, so the basic knowledge of JavaScript is often examined in the interview of large factories.

I am going to spend half a year to systematically comb out the JavaScript foundation common in some big factory interviews: JavaScript advanced. If you think it’s helpful, don’t forget to give it a thumbs up


“This” is an easy question for many interviewers to ask. This article gives a comprehensive overview of this binding in the form of a specific case.

All cases in this article can be directly verified in the browser terminal run independently, suggest that interested in the case can copy the code to try, can help better understand.

The this binding should be used

This binding has default binding (strict/non-strict mode), implicit binding, display binding (call/apply/bind), new binding, and arrow function binding (ES6), all of which have higher priority (except for arrow function binding), i.e., new binding has the highest priority and default binding has the lowest priority.

1. Default binding

When a method is called without a specific object, the default call is window or undefined, which is generally understood as the Window binding.

The default binding for this can be non-strict or strict.

Nonstrict mode

The function runs in non-strict mode, and the default binding can bind to the global object Window. Let’s start with a case study

var name = 'World beaters'

function getName () {
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,
}

getName();
Copy the code

In this case, when we execute getName(), we do not specify the object to call. The default is the global object Window, so this in getName() is bound to window, and name in window is invincible. So it will print my name is invincible.

Strict mode

In strict mode, however, you cannot use a global object for the default binding. This is bound to undefined, as in the following case:

var name = 'World beaters'

function getName () {
  // Use strict mode
  "use strict"
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,}// Execute the function
getName();
Copy the code

In this case, because this is in strict mode, it cannot be bound to all object Windows, so getName() will print the error log Uncaught TypeError: Cannot read property ‘name’ of undefined.

However, in strict mode, calling the function does not affect the default binding of this, as in the following case:

var name = 'World beaters'

function getName () {
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,}// Strict mode calls do not affect the default binding
function consoleName () {
  "use strict"
  getName();
}
// Execute the function
consoleName()
Copy the code

ConsoleName (), called getName() in strict mode can bind to the global object Window, thus printing my Name is invincible

2. Implicit binding

When a function refers to a context object, this binds to the object on which the function was called

To modify the default binding example above, call the function from the object Person as follows:

var name = 'World beaters'

function getName () {
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,
  getName,
}
// Execute the function
Person.getName()
Copy the code

Execute the person.getName () method, which specifies that the call object of the method is Person, so this is bound to Person, and the value of the property name in Person is the floor dragon, so it prints my name is floor dragon

  • When implicit binding, be carefulImplicit lossImplicitly bound functions will lose the binding object in certain cases and become the default binding, binding this to the global object window or undefined. There are two main types of scenarios:
Implicit loss – function references

When using function references, it is easy to make the implicit binding of this the default. Let’s make a change to the implicit binding case by assigning a reference to Person.getName to consoleName and executing it, as in the following case:

var name = 'World beaters'

function getName () {
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,
  getName,
}

// Add a reference to Person.getName
let consoleName = Person.getName;

// Execute the function
consoleName()
Copy the code

In this case, the method consoleName() is a reference to Person.getName, but it actually refers to the getName function itself. ConsoleName () is an undecorated function call. It is bound by default, so it binds to the global window and prints my Name is invincible

Implicit loss – callback function

The function is passed as an argument, and the callback function is implicitly assigned when executed. It is very common to lose the this binding in callback functions. Let’s make a change to the implicit binding case by passing Person.getName as an argument to consoleName, as in the following case:

var name = 'World beaters'

function getName () {
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,
  getName,
}

// Pass person. getName as an argument to consoleName
let consoleName = function (fn){
   fn()
};

// Execute the function
consoleName(Person.getName)
Copy the code

The “this” binding will be changed from an implicit binding to the default binding, binding to the global window and printing my Name is invincible

3. Explicit binding

Force this to be bound to the specified object by calling the Call /apply/bind methods.

Let’s make a change to the default binding case as follows:

var name = 'World beaters'

function getName () {
  console.log(`my name is The ${this.name}`)}let Person = {
  name: Valley Floor Dragon.age: 28,}// Execute the function
getName.call(Person);
Copy the code

GetName (‘ Person ‘); getName (‘ Person ‘); getName (‘ Person ‘)

  • Note: this is thecallSwitch toapply/bindThe effect is the same, there are some differences in use,call/apply/bindI will write a separate article to introduce it in detail.

4. The new binding

When you call a function with new, the JavaScript interpreter creates a new object underneath, which this binds to.

Take a look at the following examples:

function Person (name, age) {
  this.name = name
  this.age = age
}
// Create the object binding this with new
const person = new Person(Valley Floor Dragon.28)
console.log(`my name is ${person.name}`)
Copy the code

In this case, calling the function Person() with new creates a new object Person, which is bound to this in the function, person.name is actually this.name in the function, so it prints my name is the dragon

5. Arrow function binding

The arrow function does not have its own this; it is bound to an outer object

The arrow function was introduced in ES6 and is very handy to use and avoids many of the pitfalls of using this in ES5. Take a look at an example:

var name = "Invincible.";

var Person = {
  name : "Dragon at the Bottom.".getName: function () {
    console.log(`my name is The ${this.name}`)},consoleName: function () {
    // The callback function does not use the arrow function, which is an implicit lost case of implicit binding. This binds to the global object Window
    setTimeout(function (){
        this.getName()
    },100); }};// Execute the function
Person.consoleName()  
Copy the code

When the Person.consolename () method is executed, the callback function that calls setTimeout() internally does not use the arrow function. The callback function this binds to the object that called setTimeout(), i.e., the global window. Uncaught TypeError: this.getName is not a function Uncaught TypeError: this.getName is not a function

To modify the above example, use the arrow function as follows:

var name = "Invincible.";

var Person = {
  name : "Dragon at the Bottom.".getName: function () {
    console.log(`my name is The ${this.name}`)},consoleName: function () {
    // The callback uses the arrow function. This binds to the outer object Person
    setTimeout(() = >{
        this.getName()
    },100); }};// Execute the function
Person.consoleName()  
Copy the code

Since the arrow function does not have its own this, it points to the outer object, so setTimeout() binds this to the outer object Person, so it prints my name is the Dragon


If you think it’s helpful, don’t forget to give it a thumbs up

  • Valley Floor Dragon’s collection of tech blogs

A series of interpretations of JavaScript basics:

  • “JavaScript Advanced” explores five ways to bind this
  • Call, apply, bind, new
  • “JavaScript Advanced” looks through constructors, prototype prototypes, and prototype chains
  • “JavaScript Advanced” explores common inheritance patterns

conclusion

If you are also a programmer interested in investment and financial management, welcome to pay attention to my public account “flying dragon at the bottom of the valley”, and become the investment leader of the technology industry.