Usage functions and handwritten implementation of call, apply, and bind

usage

1.apply

applyAccepts two parameters, the first parameter is thisthe pointer, and the second parameter is the parameter accepted by the function, passed in in the form of an array

The original function will be executed immediately after changing thisthe pointer, and this method only temporarily changes thisthe pointer once.

grammar:

func.apply(thisArg, [argsArray])

thisArg: the object pointed to by this when the function is running, required
argsArray: the parameters passed when the function is running, in array form, optional

example:

function fn (a,b,c) {
    console.log(this.name)
    console.log(a, b, c)
}
let obj = {name: '科比'}
fn.apply(obj, [1,2,3])
// 输出  科比 1 2 3

2.call

Like applythe same, thisthe original function will be executed immediately after changing the pointer, and this method only temporarily changes thisthe pointer once.

The difference is that the parameters passed in apply must be in array form, while call does not have this restriction.

grammar:

func.call(thisArg[, args1, args2, args3,....])

thisArg: the object pointed to by this when the function is running, required
args1, etc.: parameters passed when the function is running, optional

example:

function fn (a,b,c) {
    console.log(this.name)
    console.log(a, b, c)
}
let obj = {name: '科比'}
fn.call(obj, 1, 2, 3)
// 输出  科比  1 2 3

3.bind

The bind method is very similar to call. The first parameter also thispoints to , and what is passed in later is also a parameter list (but this parameter list can be passed in multiple times)

After changing thisthe pointer, it will not be executed immediately, but will return a thisfunction that permanently changes the pointer.

grammar:

func.bind(thisArg[, args1, args2, args3,....])
function fn (a, b, c, d) {
    console.log(this.name)
    console.log(a, b, c, d)
}
let obj = {name: '科比'}
let bindFn = fn.bind(obj, 1, 2, 3)
bindFn('bind') // 输出  科比  1 2 3 'bind'

It can be seen from the example that a new function is returned, pointed to  bindwhen executing the new function , and then the parameters passed in are merged with the parameters passed in when the new function is called, and passed together to the new functionthisobjbind

Handwritten implementation:

You can know from the above apply, call, bind usage:

Apply, call, and bind all point to apply, which can change this
. Call will execute the called function, and bind returns a new function.
The second parameter of apply requires an array, while call and bind do not limit the data type. It will pass the remaining parameters to the function together. Bind will also merge the parameters passed in when the new function is called and pass them to the new function.
They are all bound to the Function prototype.
Let’s see how to implement it by handwriting. Because they are all bound to the Function prototype.

1.apply

Function.prototype.apply = function (context, args) {
  // 不传默认是全局,window
  context = context || window
  // args不传时默认是空数组,防止下面用spread操作符时报错
  args = args ? args : []
  // 把this存到context.fn,这里的this是调用的函数
  context.fn = this
  // 执行调用的函数,this指向context,参数用spread操作符扩展
  const res = context.fn(...args)
  // 删除,不污染context
  delete context.fn
  // 返回res
  return res
}
function fn (a,b,c) {
    console.log(this.name)
    console.log(a, b, c)
}
let obj = {name: '码上游'}
fn.apply(obj, [1,2,3])
// 输出  码上游  1 2 3

2.call

call is the same as apply. The main reason is that the parameters are different from apply. Just make small changes;

code show as below:

Function.prototype.call = function (context, ...args) {
  // 不传默认是全局,window
  context = context || window
  // args不传时默认是空数组,防止下面用spread操作符时报错
  args = args ? args : []
  // 把this存到context.fn,这里的this是调用的函数
  context.fn = this
  // 执行调用的函数,this指向context,参数用spread操作符扩展
  const res = context.fn(...args)
  // 删除,不污染context
  delete context.fn
  // 返回res
  return res
}

It is mainly used when callobtaining the second parameter of the function , so that all remaining parameters can be obtained into args, and everything else is the same.argsspread操作符

function fn (a,b,c) {
    console.log(this.name)
    console.log(a, b, c)
}
let obj = {name: '科比'}
fn.call(obj, 1, 2, 3)
// 输出  科比  1 2 3

3.bind

Bind is different. It returns a new function. This new function can be called or used as a constructor using newoperators, so a distinction needs to be made here.

Function.prototype.bind = function (context, ...args) {
  // 不传默认是全局,window
  context = context || window
  // 把this存到fn,这里的this是调用的函数
  let fn = this
  return function newFn (...fnArgs) {
    let res
    // 要考虑新函数是不是会当作构造函数
    if (this instanceof newFn) {
      // 如果是构造函数则调用new 并且合并参数args,fnArgs
      res = new fn(...args, ...fnArgs)
    } else {
      // 当作普通函数调用 也可以用上面定义的_call
      res = fn.call(context, ...args, ...fnArgs)
    }
    return res
  }
}

verify

function fn (a, b, c, d) {
    console.log(this.name)
    console.log(a, b, c, d)
}
let obj = {name: '科比'}
let bindFn = fn.bind(obj, 1, 2, 3)
bindFn('bind') // 输出  科比  1 2 3 'bind'
 
let bindFn = fn.bind(obj, 1, 2, 3)
let instance = new bindFn()
instance.constructor === fn // true

Guess you like

Origin blog.csdn.net/LoveHaixin/article/details/133038002