This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

The characteristics of

  1. This always points to an object.
  2. This refers to the functionperformWhen determined. (One of the three properties of the execution context)

Execution context concept in the articles of scope and the scope chain | August more challenges in understanding.

The rules

From the JavaScript you Don’t Know volume, used to judge this point. Order represents priority, from highest to lowest. (Arrow function does not apply)

  1. Called by new, it is bound to the newly created object.
  2. Called by call, apply, or bind to bind to the specified object.
  3. Called by the context object, bound to the context object.
  4. Default: bound to undefined in non-strict mode, otherwise bound to global object.

The following sections follow the order of the current rules, and end with a separate discussion of arrow functions.

The new call

The new constructor is called to create a new object. This points to the new object.

function person(name) {
  this.name = name
}
let obj = new person('jin line')
console.log(obj.name) / / jin
Copy the code

Call, apply, bind

Call, Apply, and bind all have the same ability to do the same thing (change the execution context object when the function is run).

call

function.call (thisArg, arg1, arg2, …)

ThisArg: Function context object. Optional arguments. Automatically replace global objects if NULL or undefined. arg1,arg2,… : Parameter list.

function introduce(job) {
  console.log(this.name + 'Is a' + job)
}
let obj = { name: 'jin line' }
let job = 'Front End Engineer'
introduce.call(obj, job) // Jinhang is a front-end engineer
Copy the code

apply

Much the same as call, except that the argument list is wrapped in an array.

function.apply(thisArg, [arg1, arg2, …] )

function introduce(job) {
  console.log(this.name + 'Is a' + job)
}
let obj = { name: 'jin line' }
let job = 'Front End Engineer'
introduce.apply(obj, [job]) // Jinhang is a front-end engineer
Copy the code

bind

Bind differs from call and apply in that it does not call a function immediately, but instead returns a function that has changed the context of the function. Note: Multiple bind is invalid.

function.bind(thisArg, arg1, arg2, …)

function introduce(job) {
  console.log(this.name + 'Is a' + job)
}
let obj = { name: 'jin line' }
let job = 'Front End Engineer'
let func = introduce.bind(obj, job) 
func() // Jinhang is a front-end engineer
Copy the code

Bind the new object to the returned function again, with the output value unchanged.

function introduce(job) {
  console.log(this.name + 'Is a' + job)
}
let obj = { name: 'jin line' }
let obj1 = { name: 'seven gold' }
let job = 'Front End Engineer'
let func = introduce.bind(obj, job).bind(obj1, job) 
func() // Jinhang is a front-end engineer
Copy the code

The second bind is to change the context object of the return function instead of the original function. Write a simple bind function that overrides the native bind implementation and executes the following code.

Function.prototype.bind = function(oThis) {
  if(typeof this! = ='function') {
      return;
  }
  var self = this.// Arguments is the list of arguments passed to bind
      args = Array.prototype.slice.call(arguments.1);
  return function() {
      // The current arguments are passed to the return function
      console.log (oThis,this)
      return self.apply(oThis, args.concat(Array.prototype.slice.call(arguments))); }}function introduce(job) {
  console.log(this.name + 'Is a' + job)
}
let obj = { name: 'jin line' }
let obj1 = { name: 'seven gold' }
let job = 'Front End Engineer'
let func = introduce.bind(obj, job).bind(obj1, job) 
func() // Jinhang is a front-end engineer
Copy the code

From the screenshot, we can conclude that the first line is func, and this refers to window. The second line is introduce.bind(obj, job), this points to obj1. Bind (obj, job); bind(obj, job); bind(obj, job); ✌

The object

If the calling location context has an object, this is bound to the specified object. Note, however, that there are cases where binding objects can be lost.

var person = {
  name: 'jin line'.getName: getName
}
var name = 'seven gold'
function getName() {
  console.log(this.name)
}
person.getName() / / jin
var func = person.getName
func() / / seven gold
Copy the code

The default

Refers to a call made directly by the function name in any scope. Features: Bound to undefined in non-strict mode, otherwise bound to a global object.

// Non-strict mode
var name = 'jin line'
function getName() {
    console.log(this.this.name)
}
getName() // Window{}, jinhang
Copy the code
// Strict mode
var name = 'jin line'
function getName() {
    "use strict"
    console.log(this.this.name)
}
getName() // Undefined, jin line
Copy the code
// Call the function scope
var name = 'jin line'		
function getName() {
    console.log(this.this.name)
}
function func() {
    getName()
}
func()
Copy the code

Arrow function

The above rules no longer apply to arrow functions. The arrow function this inherits the this binding from the outer function and has no binding to this itself. The arrow function this cannot use new, call, apply, or bind to change the execution context.

let obj = {name: 'jin line'}
let obj1 = {name: 'seven gold'}
function getName() {
  return () = > {
    / / foo inheritance
    console.log(this.name)
  }
}
let func = getName.bind(obj)
let func1 = func().bind(obj1) 
func1() // Output jin line
Copy the code

reference

JavaScript this point to the problem of JavaScript in-depth parsing JavaScript in-depth bind simulation implementation