Detailed Explanation of call apply and bind Methods of JavaScript Function

  • 2021-11-13 06:21:59
  • OfStack

Summarize

1. Similarities

Can change the direction of the internal this when the target function is executed The first parameter of the method is used to specify the internal this value when the function is executed Supports passing arbitrary parameters to the objective function If undefined and null are not passed to the first parameter of the method, this in the target function points to window object in JavaScript normal mode, and undefined and null in strict mode respectively.

2. Differences

The apply () method can take two parameters, while the call () and bind () methods can take multiple parameters. The apply () method passes arguments to the target function only by using an array of arguments or an arguments object as the second argument of the method, while the call () and bind () methods enumerate the arguments one by one after the first argument of the method. When the call () and apply () methods are called, the target function is executed immediately, whereas the bind () method does not. It returns a new function-a copy of the target function, the this inside which points to the first parameter of the bind () method, and then executing the new function is equivalent to executing the target function. Only the bind () method implements the Curritization of the function, so the parameters can be passed to the objective function twice.

call () method

Calling the call () method immediately executes the target function, changing the direction of the this inside the function. The this point is determined by the first parameter of the method, and any parameter enumerated one by one later is passed as parameter 11 of the objective function. For the last point of the same point in the beginning summary, an example is as follows:

/*  Normal mode  */

let obj = {
  sum(a, b) {
    console.log(this)
    return a + b
  }
}

//  Execute  sum  Functional  apply , bind  Method, printed  this  Same as below 
obj.sum.call()  //  Print  window
obj.sum.call(undefined, 1, 2)  //  Print  window
obj.sum.call(null, 1, 2)  //  Print  window

/*  Strict model  */
'use strict'

//  Execute  sum  Functional  apply , bind  Method, printed  this  Same as below 
obj.sum.call()  //  Print  undefined
obj.sum.call(undefined, 1, 2)  //  Print  undefined
obj.sum.call(null, 1, 2)  //  Print  null

Analog implementation

1. Key points

The myCall () method is added to the Function prototype object, and when the target function calls the method, the this inside the myCall () method points to the target function. The target function is executed as a method of the context object, whereby the this inside the target function points to the context object. . Delete the target function from the context object Use the extension operator... to process arguments passed into the target function

2. In the simulation implementation of call (), apply () and bind (), when the first parameter is not passed or undefined and null are passed, the this in the normal mode and strict mode of JS is treated in a unified way, that is, this in the objective function points to window objects.

3. The code is as follows


Function.prototype.myCall = function (context, ...args) {
  if (context === undefined || context === null) {
    context = window
  }
  //  The following behavior core code 
  context.fn = this
  const result = context.fn(...args)
  delete context.fn
  return result
}

let obj1 = {
  basicNum: 1,
  sum(a, b) {
    console.log(this)
    return this.basicNum + a + b
  }
}
let obj2 = {
  basicNum: 9
}
console.log(obj1.sum.call(obj2, 2, 3))  // 14
console.log(obj1.sum.myCall(obj2, 2, 3))  // 14

apply () method

Calling the apply () method immediately executes the target function, changing the direction of the this inside the function. The this point is determined by the first parameter of the method, and the second parameter is an array of parameters or an arguments object, and the parameters represented by each array element or an arguments object are passed in correspondingly as parameter 11 of the target function.

Analog implementation

1. Key points

The myApply () method is added to the Function prototype object, and when the target function calls the method, the this inside the myApply () method points to the target function. The target function is executed as a method of the context object, whereby the this inside the target function points to the context object. Delete the target function from the context object Use the extension operator... to process arguments passed into the target function

2. The code is as follows


Function.prototype.myApply = function (context, args) {
  if (context === undefined || context === null) {
    context = window
  }
  //  The following behavior core code 
  context.fn = this
  const result = context.fn(...args)
  delete context.fn
  return result
}

console.log(obj1.sum.apply(obj2, [2, 3]))  // 14
console.log(obj1.sum.myApply(obj2, [2, 3]))  // 14

bind () method

Calling the bind () method will return a new function-a copy of the target function. The this inside the function points to the first parameter of the method, and any parameters listed one by one will be passed in as parameter 11 of the target function. After that, executing the new function is equivalent to executing the target function. The bind () method implements the Curritization of the function, so the parameters can be passed to the objective function in two times, the first time the parameters are enumerated after the first parameter of the bind () method, and the second time the parameters are enumerated in the new function.

Analog implementation

1. Key points

The myBind () method is added to the Function prototype object, and when the target function calls the method, the this inside the myBind () method points to the target function. The target function is executed as a method of the context object, whereby the this inside the target function will point to the context object. Delete the target function from the context object Use the extension operator... to process the initial parameters and subsequent parameters passed into the target function.

2. The code is as follows


Function.prototype.myBind = function (context, ...initArgs) {
  if (context === undefined || context === null) {
    context = window
  }
  //  Cache  this  Value 
  const _this = this
  return function (...args) {
    //  The following behavior core code 
    context.fn = _this
    const result = context.fn(...initArgs, ...args)
    delete context.fn
    return result
  }
}

console.log(obj1.sum.bind(obj2, 2)(3))  // 14
console.log(obj1.sum.myBind(obj2, 2)(3))  // 14

Related knowledge points

On the Direction of this in JavaScript

Related articles: