So let’s look at some code like this

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

func()()
Copy the code
let obj = {
  func() {
  	function f() {
      return this
    }
    console.log(f())
    return f
  }
}

obj.func()()
Copy the code
function T() {
	this.func = function() {
		function f() {
      return this
    }
    console.log(f())
    return f
	}
}

let obj = new T()
obj.func()()
Copy the code
function T() {}
T.prototype.func = function() {
  function f() {
    return this
  }
  console.log(f())
  return f
}

let obj = new T()
obj.func()()
Copy the code
class T {
  func() {
    function f() {
      return this
    }
    console.log(f())
    return f
  }
}

let obj = new T()
obj.func()()
Copy the code
class T {
  static func() {
    function f() {
      return this
    }
    console.log(f())
    return f
  }
}

T.func()()
Copy the code

In all the other cases, the internal function of the nested function refers to the global object Window. In the other two cases, the internal function of the nested function refers to the global object window.

The above examples show the methods of most function calls. We want to explore what the this of a function inside a nested function refers to.

Before we explore, we know the following

  • Internal of a functionthisAlways point at run time
  • The interior of a directly called function or self-executing functionthisPointing to a global object

The class example of ES6 should behave the same as the other examples. Why does it point to undefined? There must be something different inside the class.

In search of ES6 class source code found such a warehouse: there is an ES6 class conversion into ordinary function writing transcoder.

We see that class can actually be escaped like this:

// Classes
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  get name() {
    // Template strings
    return `The ${this.firstName} The ${this.lastName}`;
  }

  toString() {
    return this.name; }}// Normal Function
var $__Object$defineProperties = Object.defineProperties;

var Person = function() {
  "use strict";

  function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  $__Object$defineProperties(Person.prototype, {
    name: {
      get: function() {
        // Template strings
        return "" + this.firstName + "" + this.lastName + "";
      },

      enumerable: true.configurable: true
    },

    toString: {
      value: function() {
        return this.name;
      },

      enumerable: false.writable: true}});returnPerson; } ();Copy the code

The result of escaping our example would be:

var $__Object$defineProperties = Object.defineProperties;

// instance method
var T = function() {
  "use strict";

  function T() {}

  $__Object$defineProperties(T.prototype, {
    func: {
      value: function() {
        function f() {
          return this
        }
        console.log(f())
        return f
      },

      enumerable: false.writable: true}});returnT; } ();let obj = new T()
obj.func()()

// static method
var T = function() {
  "use strict";

  function T() {}

  $__Object$defineProperties(T, {
    func: {
      value: function() {
        function f() {
          return this
        }
        console.log(f())
        return f
      },

      enumerable: false.writable: true}});returnT; } (); T.func()()Copy the code

This is actually the same as the normal function we wrote above, except that this is “use strict”. First, two examples of escaped code are executed normally on the console, and the result is still this pointing to undefined; Then we try to delete “use strict”, and this does refer to window again.

So this is all about strict mode.

For the explanation of strict mode, we can refer to the teacher Ruan Javascript strict mode in detail to explain this article, the point mentioned in the article is to explain the phenomenon of this problem.

Finally, by the way, a brief summary of the impact of using strict mode:

  • Global variables must be explicitly declared
  • Disallow the with statement
  • Create the eval scope
  • Disallow the this keyword from pointing to global objects
  • Disallow traversal of the call stack within a function, restrictionargumentsThe use of
  • Disallow variable deletion
  • Object attributes and function parameters have the same name
  • Functions must be declared at the top level
  • New reserved word