手写call、apply、bind

113 阅读1分钟

1. 基本用法

call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,

第二个参数差别:

1、call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,依次放到后面

PS:obj.myFun.call(_this,'param1', ... ,'params');

2、apply的所有参数都必须放在一个数组里面传进去

PS: obj.myFun.apply(_this,['param1', ..., 'params']);

3、bind除了返回是函数以外,它的参数和call 一样。需要调用执行

PS: obj.myFun.bind(_this,'param1',... ,'params') () ;

2.手写

2.1 手写call

Function.prototype.zh_call = function (thisArg, ...args) {
  // 1.获取需要被执行的函数
  var fn = this;

  // 2.对thisArg转成对象类型(防止它传入的是非对象类型)
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window;

  // 3.调用需要被执行的函数
  thisArg.fn = fn;
  var res = thisArg.fn(...args);
  delete thisArg.fn; //把这个多余的属性删除

  // 4.将最终的结果返回出去
  return res;

}

// **************调用********************

function foo() {
  console.log("foo函数被执行", this)
}

function sum(num1, num2) {
  console.log("sum函数被执行", this, num1, num2)
  return num1 + num2
}


// 自己实现的函数的zh_call方法
// 默认进行隐式绑定
foo.zh_call({ name: "blueheart" })
foo.zh_call(undefined)
var result = sum.zh_call("zhleon521", 20, 30)
console.log("zh_call的调用:", result)

image.png

2.2 手写apply

Function.prototype.zh_apply = function(thisArg, argArray) {
  // 1.获取到要执行的函数
  var fn = this

  // 2.处理绑定的thisArg
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window

  // 3.执行函数
  thisArg.fn = fn
  var result
  // if (!argArray) { // argArray是没有值(没有传参数)
  //   result = thisArg.fn()
  // } else { // 有传参数
  //   result = thisArg.fn(...argArray)
  // }

  // argArray = argArray ? argArray: []
  argArray = argArray || []
  result = thisArg.fn(...argArray);

  delete thisArg.fn;

  // 4.返回结果
  return result;
}

2.3 手写bind

Function.prototype.zh_bind = function(thisArg, ...argArray) {
  // 1.获取到真实需要调用的函数
  var fn = this

  // 2.绑定this
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window

  function proxyFn(...args) {
    // 3.将函数放到thisArg中进行调用
    thisArg.fn = fn
    // 特殊: 对两个传入的参数进行合并
    var finalArgs = [...argArray, ...args]
    var result = thisArg.fn(...finalArgs)
    delete thisArg.fn

    // 4.返回结果
    return result
  }

  return proxyFn
}