【javascript源码】call,apply,bind 方法实现(前端面试)

102 阅读2分钟

众所周知,call,apply以及bind函数的实现在前端面试手写题中经常考到,这个体现js基本功的一个重要考量,那么我们今天就来实现一下对应的模拟源码(附上详解)。

前期准备

准备好一个对象以及一个函数,准备来将func的this指向到obj的对象中。

    let obj = {
      name:'老周'
    }
    function func(age,gender){
      console.log("名字为"+this.name)
      console.log("我的年龄是"+age)
      console.log("我的性别是"+gender)
    }

源码模块

call函数模拟(第二,三...参数是func函数运行时传入的参数)

function myCall(context,...args){
      // 1.首先在context上下文对象(此处指的是上文的obj)中添加入func这个键值对。
      // this则是实例化引用对象,也就是最后调用myCall方法的func。
      context.func = this
      // 2.执行context中的func函数并传入func设定的形参
      const res = context.func(...args)
      // 3.将第一步添加的func键值对删除,恢复原样,不要改变obj的原有属性
      delete context.func
      // 4.最后将func的执行结果返回出去
      return res
}
// 为了让全局的func函数能够以函数的形式调用该api,我们将我们写出的myCall方法放进Function的原型链中成为一个属性。
Function.prototype.myCall = myCall

运用一下并打印结果

func.myCall(obj,"18","男") // 名字为老周 我的年龄是18 我的性别是男

apply函数模拟

第一个参数是context上下文 传入的第二个参数是一个数组,也就是将要调用的函数func的实参数组集

function myApply(context,args){
      context.func = this 
      const res = context.func(...args)
      delete context.func
      return res
} 
Function.prototype.myApply = myApply

运用一下并打印结果

func.myApply(obj,["20","男"]) // 名字为老周 我的年龄是20 我的性别是男

bind函数模拟

此时我们就不再向上面一样重复代码了,可以套用上边的call函数。

我们知道,调用bind方法后,func是不会自动执行的,需要再次调用才能执行,所以我们这个模拟方法将return 出去一个函数

function myBind(context,...args){
      //因为此时myBind函数的内部的this指针无法让外部实例读取到,所以我们定义f变量接收this,并在return 函数之中将f变量暴露出去。
      const f = this
      return function(){
        // console.log(this) 此处打印出来就是window全局对象,并非func
        return f.myCall(context,...args)
      }
}
Function.prototype.myBind = myBind

运用一下并打印结果

func.myBind(obj,"22","男")() // 名字为老周 我的年龄是22 我的性别是男

以上就是本文的主要内容,期待学习的小伙伴认真观看并理解其中的要点,文中有缺陷的地方也欢迎评论区留言并改进。