js高级-手写apply,call,bind函数

首先声明一点,这里手写的函数跟js真正的函数的实现是不一样的,我们真正调用的apply,call,bind函数是会考虑很多边界情况的,我们这里只注重函数的核心实现逻辑,对边界问题并不做过多的处理,手写这些函数只是为了辅助理解这些函数,以达到加深印象的目的。

手写apply,call,bind函数怎么入手?

入手点:

(1)外壳:函数的声明

 首先我们要从函数声明开始,了解这个函数的函数声明两个要素(参数,返回值),并进行模拟,这样可以做到使用相同的调用方式,获取到相同的返回值,做到函数外壳的一致性,让别人用我们的函数和使用js的函数获得使用上的一致性。 

(2)逻辑:函数实现的功能

其次我们要做到功能实现的一致性,手写函数的目的就是为了模拟函数的功能实现,所以我们可以从原生函数实现的功能思考,思考它是怎么做到这样的功能的,然后进行模拟,达到与函数功能的一致性。 

(3)函数的调用方式

最后我们还需要做到和原生函数一样的调用方式,这里需要做到一点,就是任何函数都是可以调用apply,call,bind这三个函数的,所以我们实现的函数也是需要做到任何函数都可以做到。

  当我们手写的函数的声明,调用方式和函数的实现的功能都和原生函数一致时,我们就像可以说我们实现了这个函数。 

怎么做到任何函数都可以调用我们手写的函数?

这里需要用原型的概念,当我们把一个函数添加到一个对象的原型中的时候,任何是这种原型的对象,都可以使用我们添加的这个函数。因为任何函数的原型都是Function 函数这个对象的的原型,所以要做到任何函数都可以调用我们手写的函数, 我们就需要将我们的函数添加到Function 函数这个对象的原型中。

这里可以简单的将原型理解为为原型就是一个类,任何是这个类的对象,都可以使用这个类中的方法,我们将函数添加到原型中,就相当于将函数添加到了类中。由于我们是将手写的函数添加到了Function这个类中,而我们写的所有的函数都是Function这个类的对象,所以所有的函数也就可以使用我们手写的函数了。 

上述的这种理解只是为了辅助理解,真正的原型的概念并非如此,请注意。

对于原型不理解的,可以查看我关于原型的总结的文章。 

手写call函数

1.分析call函数

 fun.call(thisArg,arg1,arg2,arg3,...)
(1)参数:call函数的第一个参数是在 在 `fun`函数运行时指定的 `this`值,它和我们函数内部的this指向不是一回事,剩余参数我们调用函数需要真正传递的值。
(2)返回值:call函数的返回值,是调用call函数的函数的返回值。
(3)功能:call函数实现的功能,功能就是调用 函数。
(4)调用方式:call函数的调用方式,任何函数都可以调用 

2.call函数具体实现

 //给所有的函数都添加一个zhCall的方法,通过给Function函数的原型添加函数的形式,达到目的
    Function.prototype.zhCall = function(thisArg,...agrs){//函数接受n个参数,thisArg接收绑定对象的“this”值,...args接收剩余参数
    
    //1.获取需要执行的函数,call 函数是显示绑定this原则,所以这里的this,指向的是调用call函数的那个函数
    var fn = this
    
    //2.对thisArg转成对象类型(防止它传入的非对象类型),将其转化为一个对象,如果使用者传入的不是一个对象类型,则使用默认的window
    thisArg = (thisArg !== null && thisArg !==undefined) ? Object(thisArg):window
    
    //3.调用需要被执行的函数
    thisArg.fn = fn
    var result = thisArg.fn(...args) // 通过隐式绑定this 规则,将传递进来的this对象,传入到函数内部
    delete thisArg.fn
    
    //4.将最终的结果返回出去
    return result
    } 

手写apply函数

分析apply函数

fun.apply(thisArg,[arg1,arg2,arg3])
   (1)参数:apply函数的第一个参数是在 在 `fun`函数运行时指定的 `this`值,,第二个参数是一个数组,包含了函数调用时的剩余参数。
  (2)返回值:apply函数的返回值,是调用apply函数的函数的返回值。
  (3)功能:apply函数实现的功能,功能就是调用函数。
  (4)调用方式:apply函数的调用方式,任何函数都可以调用 

2.apply函数具体实现

 Function.prototype.zhapply = function (thisArg,argArray){
        //1.获取要执行的函数
        var fn = this
    
        //2.处理绑定的thisArg ,将其转化为一个对象,如果使用者传入的不是一个对象类型,则使用默认的window
        thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg):window
        
        //3.执行函数
        thisArg.fn = fn
        var result
        argArray =  argArray || []
        result = thisArg.fn(...argArray)  //this隐式绑定,将传入的this传递给要执行的函数
        
        delete thisArg.fn
        
        //4.返回结果
        return result
        
    
    
    } 

手写bind函数

1.分析函数

bind函数使用分两步
    (1)绑定:
         newFn = fun.bind(thisArg,第一次函数可选传入)
     (2)调用
         newFn(第二次函数参数传入)
   (1)参数:bind函数的第一个参数是在 在 `fun`函数运行时指定的 `this`值,,第二个参数是第一次可以传入的可选参数。
  (2)返回值:bind函数的返回值,是返回绑定好this值的函数本身。
  (3)功能:bind函数实现的功能,主要是实现调用绑定。
  (4)调用方式:bind函数的调用方式,任何函数都可以调用,这里需要注意的是在调用时,还可以传入其他的参数。 

2.bind函数实现

 Function.proptype.zhBind = 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
        }
        //返回要调用的函数本身,这里是添加过this绑定值的函数
        return proxyFn
    } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值