Trust me, as long as you remember the 7️ step tactic of this article, you will have a thorough grasp of this pointing in JS.

Say the formula first: arrow function, new, bind, apply and call, Obie point (OBj.), direct call, not in function.

In the order of the formulas, as long as one of the previous scenarios is satisfied, you can determine that this refers to.

They are explained in detail next, in verbal order, with the sample code running in Chrome’s Console.

At the end of the article, there are carefully prepared practice questions to test your study results. Don’t forget to try them

1. Arrow function

The arrow function is first because its “this” is not changed, so as long as the current function is an arrow function, you don’t need to look at any other rules.

The “this” of the arrow function is the point to the outer “this” when it was created. There are two key points here:

  1. When you create the arrow function, you have determined its this point.
  2. The “this” inside the arrow function points to the “this” outside.

So in order to know the “this” of the arrow function, you need to know the “this” of the outer layer, so you need to continue applying the 7-step formula to the outer layer.

2. new

When a function is called with the new keyword, this in the function must be a new object created by JS.

Readers may wonder, “If the arrow function is called with the new key, does this change the arrow function?” .

Let’s try it on the console.

func = () = > {}
new func() // throw error
Copy the code

As you can see from the console, arrow functions cannot be used as constructors, so they cannot be executed with new.

3. bind

Bind is function.prototype.bind ().

Only the value of the first bind is recognized for multiple bind attempts

Easy wrong points

function func() {
  console.log(this)
}

func.bind(1).bind(2) ()/ / 1
Copy the code

This will not be modified in the arrow function

func = () = > {
  // Where this refers to the outer layer of this, reference 7 "not in the function"
  console.log(this)
}

func.bind(1) ()// Window, table 1 is preferred
Copy the code

Bind with new

Easy wrong points

function func() {
  console.log(this.this.__proto__ === func.prototype)
}

boundFunc = func.bind(1)
new boundFunc() // Object true, tactic 2 is preferred
Copy the code

4. Apply and call

Both apply() and call() take this as the first argument. The difference is that when apply is called, the arguments are put in an array, whereas when call is called, the arguments are comma separated.

This will not be modified in the arrow function

Easy wrong points

func = () = > {
  // Where this refers to the outer layer of this, reference 7 "not in the function"
  console.log(this)
}

func.apply(1) // Window, table 1 is preferred
Copy the code

This is not modified in the bind function

Easy wrong points

function func() {
  console.log(this)
}

boundFunc = func.bind(1)
boundFunc.apply(2) // 1, tactic 3 is preferred
Copy the code

5. Obi Shan Point

function func() {
  console.log(this.x)
}

obj = { x: 1 }
obj.func = func
obj.func() / / 1
Copy the code

The arrow function and bind function have a higher priority, so you can try it yourself.

6. Direct call

When the function is called directly and does not satisfy the previous scenario, this will point to the global object. The Global object is Window in the browser environment and Global in the Node.js environment.

Let’s start with a simple example.

function func() {
  console.log(this)
}

func() // Window
Copy the code

To take a more complex example, the outer layer outerFunc is designed to confuse.

function outerFunc() {
  console.log(this) // { x: 1 }

  function func() {
    console.log(this) // Window
  }

  func()
}

outerFunc.bind({ x: 1}) ()Copy the code

7. Not in a function

Scenarios that are not in functions can be divided into tags in the browser, or the module file in Node.js.

  1. in<script />In the tag, this points to Window.
  2. In the node.js Module file, this points to the Module’s default export object, module.exports.

Non-strict mode

The strict model was proposed in ES5. Before the ES5 specification, this could not be undefined or null in non-strict mode. So ** in non-strict mode, if this points to undefined or null, then this will point to the global object. ** The Global object is Window in the browser environment and Global in the Node.js environment.

For example, in non-strict mode, this refers to a global object.

function a() {
  console.log("function a:".this)
  ;(() = > {
    console.log("arrow function: ".this)
  })()
}

a()

a.bind(null)()

a.bind(undefined)()

a.bind().bind(2)()

a.apply()
Copy the code

In non-strict mode, the execution result is:

In strict mode, the same code is executed for comparison. Remember to copy and paste all the code into the console at once in order to run in strict mode (because the first line of “use strict” only takes effect on subsequent code).

"use strict"

function a() {
  console.log("function a:".this)
  ;(() = > {
    console.log("arrow function: ".this)
  })()
}

a()

a.bind(null)()

a.bind(undefined)()

a.bind().bind(2)()

a.apply()
Copy the code

The execution result in strict mode is as follows:

The seven-step formula is complete in both strict and non-strict mode, except that null or undefined is converted to global objects in non-strict mode. So I didn’t include that in the formula.

Review to solve the problem.

Arrow function, new, bind, apply and call, obie point, direct call, not in function.

1. What is the value of func.count after the following code is executed?

function func(num) {
  this.count++
}

func.count = 0
func(1)
Copy the code

The answer

Func. count is 0.

According to the formula, func() is called as a “direct call” of class 6. In non-strict mode, this points to a global object. This has nothing to do with func, so func.count stays the same. So easy.

2. Who does this point to in the following arrow function?

obj = {
  func() {
    const arrowFunc = () = > {
      console.log(this._name)
    }

    return arrowFunc
  },

  _name: "obj",
}

obj.func()()

func = obj.func
func()()

obj.func.bind({ _name: "newObj" })()()

obj.func.bind()()()

obj.func.bind({ _name: "bindObj" }).apply({ _name: "applyObj"}) ()Copy the code

The answer

// obj
// undefined
// newObj
// undefined
// bindObj
Copy the code

Was it easy? Did you lose it?

If you learn it, please like and follow it ~

If not, like this article and watch it several times

If in doubt, please comment ~