Beginners about this understanding has been very vague, about this interview questions more make head big.

This is the body of the function execution (by whom) remember: who is this and where the function was created or executed

Most interview questions can be easily solved by following these rules to distinguish the subject of execution.

1. Bind a method to an event on an element that triggers the execution of the methodthisIs the element of the current operation (implicit binding)

document.body.onclick = function() {
  // this: body
}
Copy the code

Typically, the value of this is a reference to the element that triggered the event, which is desirable when multiple similar elements use the same common event listener. When an element is registered for an event using addEventListener(), the this value in the handle is a reference to the element. This is the same as the value of the currentTarget property of the Event argument passed to the handle.

2. Execute the method to see if there is any (.) in front of the method. If there is, who is in front of the dotthisThat’s who (implicit binding), no pointthisiswindow(In strict mode (“use strict“) no pointthisisundefined, also known as default binding)

Note: the self-executing function(‘ (function(){… })() ‘this’ is usually a window

function fn() {
  console.log(this)}let obj = {
  fn: fn
}
fn()
obj.fn()
Copy the code

Output: Window object obj object

The above code is equivalent to:

let obj = {
  fn: function fn() {
    console.log(this)
  }
}
fn()
obj.fn()
Copy the code

Functions are defined inside objects, but they are qualitatively equivalent to declaring functions outside objects and then referencing functions inside objects by property names.

In a chain of object properties,thisThe binding is the innermost object

As follows:

var obj = {
  a: 1.obj2: {
    a: 2.obj3: {
      a: 3.getA: function () {
        console.log(this.a)
      }
    }
  }
}
obj.obj2.obj3.getA()
Copy the code

This: obj.obj2.obj3

3. In constructor mode execution, in the function bodythisIs an instance of the current class

When the new operation is performed, a new object is created and the constructor’s this points to the new object being created. The JS compiler does four things:

  1. Create a new empty object
  2. Link this object to the prototype object
  3. This object is bound to this
  4. If the function returns nothing, then return this by default
  function Fn(name) {
    // this: instance of the Fn class
    this.name = name
  }
  var f1 = new Fn('qxj')
  var f2 = new Fn('lx')
  console.log(f1.name)
  console.log(f2.name)
Copy the code

Output: QXJ Lx

4. Call /bind/apply can be changedthisPointing to (explicit binding)

Call (object) FN: the function you call, object: the object you want to bind to this of the function. Fn. Call (object)

  1. Call this function now (fn)
  2. When this function is calledthisPoint to object

Example:

var obj = {
  a: 1.// A is an attribute defined in object obj
  fire: function () {
    console.log(this.a)
  }
}
var a = 2        // A is a variable defined in the global environment
var fireInGrobal = obj.fire
fireInGrobal()   / / = > 2
fireInGrobal.call(obj) / / = > 1
Copy the code

FireInGroba, which lost the this parameter bound to obj, rebinds this back to obj

However, we don’t like the idea of relying on call every time. We would prefer to return this once and permanently bound to obj’s fireInGrobal function so that we don’t have to put call on the tail every time we call fireInGrobal.

What to do? This is even easier if you use bind

var fireInGrobal = function () {
    fn.call(obj)   / / hard binding
}
Copy the code

It can be simplified as:

var fireInGrobal = fn.bind(obj);
Copy the code

Call differs from bind: while binding this to an object parameter:

  1. Call will execute this function immediately

  2. Bind does not execute functions, only returns a function that can be executed

【 Others 】 : Apply is not much different from Call except how it is used

5. Arrow function

The arrow function ignores all of these rules, and the value of this is the lexical scope of the function’s creation, independent of how it was called. Compare these two examples:

function Person() {
  this.age = 0
  setTimeout(function () {
    console.log(this.age)     // => undefined
  }, 1000)}var p = new Person()

function Person() {
  this.age = 10
  setTimeout((a)= > {
    console.log(this.age)     / / = > 10
  }, 1000)}var p = new Person()
Copy the code

In the example above without the arrow function, the function inside setTimeout is called by global, which has no age property, so undefined is output.

The second example uses the arrow function, and this uses this of the lexical scope, which is Person, so it prints 10.

According to the MDN document, the value of this of the arrow function is the environment when it is created. Although the point of this in the arrow function cannot be changed by bind, call, apply and other operations, the value of this in the external environment can be changed. In other words, to change this of the arrow function, you only need to change this of the external environment. Consider the following examples:

const obj = {
  name: 'this point to obj,
  bar() {
    const x = (a)= > this
    return x
  },
}
console.log(obj.bar()())
const a = {name: 'this points to a'}
const b = {name: 'This refers to b instead of obj and a'}
console.log(obj.bar.bind(b)().call(a))
Copy the code

Output:

Summary: Binding priority

  1. Arrow function
  2. Keyword new tone
  3. Explicitly bound
  4. Implicit binding
  5. The default binding

The arrow function has the highest priority and ignores binding rules 2-5. The default binding has the lowest priority. The default binding is used only when no other binding is used.

6. A few interview questions

eg1:

var fullName = 'language'
var obj = {
  fullName: 'javascript'.prop: {
    getFullName: function () {
      return this.fullName
    }
  }
}
console.log(obj.prop.getFullName())
var test = obj.prop.getFullName
console.log(test())
Copy the code

Output: javascript language

This is obj.prop. GetFullName (). This is obj.prop. FullName is javascript. Test () is not preceded by a dot, this is window, and window.fullname is language;

eg2:

var val = 1
var json = {
  val: 10.dbl: function () {
    val *= 2
  }
}
json.dbl()
console.log(json.val + val)
Copy the code

Output: 12

Json.dbl () : this = json; val== 10; val==2; val==2; Json. val + val => 12;

Let’s change the title:

var val = 1
var json = {
  val: 10.dbl: function () {
    this.val *= 2
  }
}
json.dbl()
console.log(json.val + val)
Copy the code

Output: 21

var val = 1
var json = {
  val: 10.dbl: function () {
    this.val *= 2				// json.val = 20
  }
}
json.dbl()			// The method starts with this: json
console.log(json.val + val)		// 20 + 1 => 21
Copy the code

eg3:

var num = 10
var obj = {num: 20}
obj.fn = (function (num) {
  this.num = num * 3
  num++
  return function (n) {
    this.num += n
    num++
    console.log(num)
  }
})(obj.num)
var fn = obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num)
Copy the code

Output: 22, 23, 65, 30