Earlier we said that this is bound at run time, not at write time. JavaScript’s this always refers to an object that is dynamically bound at runtime based on the execution environment of the function, not the environment in which the function was declared.

The direction of this can be roughly divided into the following types:

  • As a method call to the object, this refers to the object
  • 2. As a normal function, this refers to the window
  • Constructor call, this refers to the object returned
  • 4, arrow function, arrow function this binding, the function of this under the definition of the object, which is bound to the object, if there is nesting case, this binding to the nearest object

As for the fixation of the arrow function this, it is not because the arrow function has a mechanism to bind this. The actual reason is that the arrow function does not have its own this, so the inner this is the this of the outer code block. Because it does not have this, it cannot be used as a constructor.

Method invocation as an object

var obj = {
  a: 1,
  getA: function() {
    console.log(this === obj)  // true
    console.log(this.a) // 1
  }
}
obj.getA()
Copy the code

Constructor call

var MyClass = function() {
  this.name = 'sven'
}
var myclass = new MyClass()
console.log(myclass.name) // 'sven'
Copy the code

Implicit binding

Only the previous or last level in the object attribute reference chain is relevant at the call location, and this in Foo points to obj2, the nearest level

function foo() {
  console.log(this.a)
}
var obj2 = {
  a: 42,
  foo: foo
}
var obj1 = {
  a: 42,
  obj2: obj2
}
obj1.obj2.foo() // 42
Copy the code

Change the direction of this

  • 1. Use the arrow function of ES6
  • Use that = this inside the function
  • 3, Use apply, call, bind
  • 4. New instantiates an object

Use apply and call to change this. The first argument is to point to this. If this is null, this points to the default host object, or window in the browser. The second argument, apply, is an array or class array, and call is arg1,arg2… In this form.

How to implement a call, apply

var foo = { value: 1 }; function bar() { console.log(this.value); } bar.call(foo); / / 1Copy the code

As you can see from the code above, call changes the reference of this to Foo, and the bar function executes. We mentioned above that as a method call to an object, this refers to the object and therefore can get its properties. So we can use this principle to implement call:

  • 1. Set functions to properties of objects
  • 2. Execute this function
  • 3. Delete the attribute
Function.prototype.call = function (context) { var context = Object(context) || window; // The first argument is null pointing to window context.fn = this; var args = []; for (var i = 1, len = arguments.length; i < len; I++) {/ / get the call at the back of the parameters of the args. Push (' the arguments [' + I + '] '); } var result = eval('context.fn(' + args + ')'); // Place the parameters in the methods in sequence and execute delete context.fn return result; }Copy the code

How to implement a BIND

Bind returns a function, which is not executed immediately. The second one takes arguments (the first argument points to this, and the following arguments are passed).

Function.prototype.bind2 = function (context) { var self = this; / / get bind2 function from the second parameter to the last parameter var args = Array. The prototype. Slice. The call (the arguments, 1); var fbound = function () { self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments))); } return fbound; }Copy the code