温故知新(九二)实现 call,bind,apply

本文详细介绍了如何在JavaScript中手动实现call()、bind()和apply()方法,包括它们的工作原理、示例代码和应用场景。重点讲解了如何绑定this值和传递参数,以及bind()方法的特性。
摘要由CSDN通过智能技术生成

手动实现 call,bind,apply

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

答案:

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组

Function.prototype.myCall = function(context,...args){
    //谁调用的call,谁就是这个this,必须是一个function,比如:fn.call(obj,1,2,3),这时候fn就是我们拿到的this
    if(typeof this !== 'function'){
        throw new TypeError('not function!');
    }
    const fn = this;
    let result = null;

    context = context || window;
    //把fn 赋值给传入的要绑定的this对象,所以fn里面的fn就变成了 上面传入的context
    context.fn = fn;
    //执行fn
    result = context.fn(...args);
    //删除context.fn属性,解除引用
    delete context.fn;
    //返回执行结果
    return result;
}

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

使用apply:

if (!Function.prototype.bind) (function(){
  var slice = Array.prototype.slice;
  Function.prototype.bind = function() {
    var thatFunc = this, thatArg = arguments[0];
    var args = slice.call(arguments, 1);
    if (typeof thatFunc !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - ' +
             'what is trying to be bound is not callable');
    }
    return function(){
      var funcArgs = args.concat(slice.call(arguments))
      return thatFunc.apply(thatArg, funcArgs);
    };
  };
})();

思路

1.拷贝源函数:

  • 通过变量储存源函数

  • 使用Object.create复制源函数的prototype给fToBind

2.返回拷贝的函数

3.调用拷贝的函数:

  • new调用判断:通过instanceof判断函数是否通过new调用,来决定绑定的context

  • 绑定this+传递参数

  • 返回源函数的执行结果

 

Function.prototype.myBind = function (objThis, ...params) {
    const thisFn = this; // 存储源函数以及上方的params(函数参数)
    // 对返回的函数 secondParams 二次传参
    let fToBind = function (...secondParams) {
        console.log('secondParams',secondParams,...secondParams)
        const isNew = this instanceof fToBind // this是否是fToBind的实例 也就是返回的fToBind是否通过new调用
        const context = isNew ? this : Object(objThis) // new调用就绑定到this上,否则就绑定到传入的objThis上
        return thisFn.call(context, ...params, ...secondParams); // 用call调用源函数绑定this的指向并传递参数,返回执行结果
    };
    fToBind.prototype = Object.create(thisFn.prototype); // 复制源函数的prototype给fToBind
    return fToBind; // 返回拷贝的函数
};

 

 

apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或类数组对象)的形式提供的参数。


Function.prototype.myApply = function(context,argArr){
    if(typeof this !== 'function'){
        throw new TypeError('not function');
    }
    if(argArr && !Array.isArray(argArr)){
        throw new TypeError('the second argument need an array');
    }
    const fn = this;
    let result = null;

    context = context || window;
    argArr = argArr || [];
    context.fn = fn;
    result = context.fn(...argArr);
    delete context.fn;

    return result;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值