手写 call / apply /bind 函数

用于 this 的显示绑定(箭头函数不绑定this)

1 call 函数的实现

// 给所有的函数添加一个hycall的方法 原型
Function.prototype.hycall = function(thisArg, ...args) {
    // 在这里可以去执行调用的那个函数(foo)
    // 问题: 得可以获取到是哪一个函数执行了hycall
    // 1.获取需要被执行的函数
    var fn = this;

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

    // 3.调用需要被执行的函数
    thisArg.fn = fn;
    var result = thisArg.fn(...args);
    delete thisArg.fn;

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

2 apply函数的实现

Function.prototype.hyapply = 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;
};

3 bind函数的实现

Function.prototype.hybind = 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
}

 4 区别对比

  • call、apply、bind相同点:都是改变this的指向,传入的第一个参数都是绑定this的指向,在非严格模式中,如果第一个参数是null或者undefined,会把全局对象(浏览器是window)作为this的值,要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
  • call和apply唯一的区别是:call传入的是参数列表,apply传入的是数组,也可以是类数组
  • bind和call、apply的区别: bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入
  • 值得注意:当 bind 返回的函数 使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用)

猜你喜欢

转载自blog.csdn.net/m0_50789696/article/details/129251879
今日推荐