The orientation of this is determined at call time, not at write time. This is the opposite of closures.

// Declare the location
var me = { 
    name: 'xiuyan'.hello: function() { 
        console.log('Hello, I amThe ${this.name}`)}}var you = { 
    name: 'xiaoming'.hello: function() { 
        var targetFunc = me.hello targetFunc() 
    }
 }
 var name = 'Bamboo'
 // Call location
 you.hello()  / / output Bamboo
Copy the code

“This refers to the object on which the method was called.”

In this example, the targetFunc method returns Bamboo. The reason why you might think that this should point to you is because of the confusion between “declare position” and “call position”. We see that although targetFunc is declared in the hello method of the you object, when we call it, we do not prefix targetFunc with any object. So the “this” of the “you” object doesn’t magically automatically pass into targetFunc, the JS engine still thinks targetFunc is a method mounted on the window, and points this to the window object.

In this way, the declaration position and the call position are deliberately mixed together, testing your ability to distinguish between the two. But as long as you keep in mind the core principle that “no matter where a method is written, its this follows its caller”, you can’t go wrong.

There are three special cases in which this refers 100% to the window:

  • Execute functions now (IIFE)
  • The function passed in setTimeout
  • The function passed in setInterval

Execute function immediately

An immediate function is an anonymous function that is called immediately after it is defined (see the following example in the body of the Hello method).

Var name = 'Bamboo' var me = {name: 'Bamboo' var me = {name: 'Bamboo',} sayHello: function() {console.log(' hello, I'm ${this.name} ')}, hello: Function () {(function(cb) {cb()})(this.sayHello)}} me. Hello ();Copy the code

Hello is Bamboo, which is the value of window.name.

However, even if you ignore the so-called “special case” of an anonymous function that executes immediately, you will get the same result if you follow our pointing principle above. As an anonymous function, we usually call it directly and do not (or cannot) assign it an object in the form of a property accessor, so its this is quite certain that it is the default global object window.

Functions passed in setTimeout and setInterval

Considering that the this pointing mechanism of setTimeout and setInterval functions is actually the same, we can start with setTimeout:

var name = 'Bamboo' var me = { name: 'xiuyan', hello: Function () {setTimeout(function() {console.log(' Hello, I am ${this.name} ')}} meCopy the code

Isn’t that amazing? Ours looks like it was called in me.hello (), but instead outputs window.name. What exactly does setTimeout do to the function?

In fact, we see the delay effect (setTimeout) and the timing effect (setInterval), are implemented under the global scope. Functions passed in either setTimeout or setInterval are first delivered to the global object. Therefore, the value of this in the function is automatically referred to the window.

The strict mode of “danger”

Before we start our column, many of you have heard the saying “Windows will become undefined in strict mode”.

In some books, it is also emphasized that the value of this in the setTimeout passed function refers to the window object in non-strict mode, but is undefined in strict mode. It seems that undefined is a necessity as long as strict patterns are added — is that true?

In fact, strict mode does cause this to point to undefined in some cases, but not always — yes, things are not simple and we need to look at each case:

How this behaves in strict mode in normal functions

By “ordinary functions”, we are referring here to the arrow function. In non-strict mode, when a normal function is called directly, as we said at the beginning, this in the function defaults to a global variable (window or global) :

Function showThis() {console.log(this)} showThis() // Outputs Window objectsCopy the code

In strict mode, this retains the value of the object to which it is assigned, so if no object is specified, this is undefined:

'use strict'

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

showThis() // undefined
Copy the code

How this behaves in strict mode in global code

This in global code is this in functions/code sections executed in global scope, which can look like this:

'Use strict' console.log(this) // Directly attempts to fetch this in the global codeCopy the code

It could also go something like this:

'strict' var name = 'Bamboo' var me = {name: 'Bamboo', hello: Function () {setTimeout(function() {console.log(' hello, I'm ${this.name} ')})}} me.hello() // Hello, I'm BambooCopy the code

In global code like this, whether it is in strict mode or not, its this refers to Window.

So strict is “dangerous.” Where is it dangerous? Undefined is terrible, it often makes our code error culprit. However, from the perspective of assisting everyone in the interview, it is undoubtedly more dangerous to see ‘use strict’ and immediately assume that this will be undefined. Therefore, we should keep in mind the different behaviors of this in strict mode

Arrow function

This in the arrow function is special, it has nothing to do with strict mode, non-strict mode, etc. It is similar to closures in that they are “dead dead” – “lexical scoped” guys. So the arrow function “this” does not depend on how you call it, but on where you write it. For example:

Var name = 'Bamboo' var me = {name: 'xiuyan', // () => {console.log(this.name)}} // Call position me.hello() // BambooCopy the code

In this case, because this is written in a global scope, it is bound to the global object.

Understanding the this pointing rule for arrow functions and the pointing rule for ordinary functions requires two completely opposite sets of brain circuits. When the two concepts get mixed up like this, the interviewer gets excited. The arrow function “this” and the normal function “this” are used together.

Q: What is the output of the following two function calls? Why is that?

var a = 1
var obj = {
  a: 2,
  func2: () => {
    console.log(this.a)
  },
  
  func3: function() {
    console.log(this.a)
  }
}

// func1
var func1  = () => {
  console.log(this.a)
}

// func2
var func2 = obj.func2
// func3
var func3 = obj.func3

func1()
func2()
func3()
obj.func2()
obj.func3()
Copy the code

The answer is 1, 1, 1, 1, 2.