js手写call、apply、bind方法

call

逐步实现,最后得出最终版
先熟悉一下call的功能及使用

 需求:想让函数打印出user 的name,即想让函数中的this指向user(修改this指向)
   const user = {
        name: "zhangsan"
    }
    function sayYourName(title) {
        console.log(title,this.name)
    }
    // 使用js内置的api call方法
    sayYourName.call(user,'hello')    //函数立即调用,并打印
    // 或者利用对象属性 直接调用
     const user1 = {
        name: "zhangsan",
        sayYourName:function(title) {
            console.log(title,this.name)
        }
    }
    user1.sayYourName('hello')
    

根据上面的思路,我们自己一个封装一个call方法

 function myCall(fn,context,...args){ // ES6剩余参数
        context.fn = fn
        const res = context.fn(...args)//扩展运算符
        delete context.fn
        return res
    }
    myCall(sayYourName,user,'hello')

// 优化:如果context 里面本身就有一个fn的属性,给它重新赋值,然乎又删掉,明显不合理,所以要保证利用的属性名的唯一性
function myCall(fn,context,...args){ // ES6剩余参数
        const fnName = Symbol()
        context[fnName]=fn
        const res = context[fnName ](...args)//扩展运算符
        delete context[fnName ]
        return res
    }
    myCall(sayYourName,user,'hello')

总结:

  1. 先把函数赋值给目标的的属性
  2. 利用目标对象对象 调用函数
  3. 删除目标对象的属性
  4. 将函数结果返回
    但是仍然封装好的myCall方法并不能采用 函数.myCall的形式调用

js内置的call方法 采用 函数.call的形式调用,但是函数本身并没有call方法,js就会向函数的原型链上查找,其实call方法就是存在与 Function.prototype上的一个属性。

所以我们进行下一步:把我们的myCall方法也挂载到函数原型上

Function.prototype.myCall = function(fn,context,...args){
		const fnName = Symbol()
        context[fnName]=fn
        const res = context[fnName ](...args)//扩展运算符
        delete context[fnName ]
        return res
}
//使用:
sayYourName.myCall(sayYourName,user,'hello')
  1. 我们不难发现 myCall方法中的this是调用它的对象,即sayYourName,所以实参中的sayYourName可以用this代替
  2. 同时我们的函数形参也要替换成this,如下:call最终版
Function.prototype.myCall = function(context,...args){
   	const fnName = Symbol()
       context[fnName]=this
       const res = context[fnName ](...args)//扩展运算符
       delete context[fnName ]
       return res
}
//使用:
sayYourName.myCall(user,'hello')

apply

基本与myCall实现一样,只是apply的传参形式为数组

Function.prototype.myApply = function(context,args){  //只需要把...args 去掉...,直接传递数组过去
   	const fnName = Symbol()
       context[fnName]=this
       const res = context[fnName ](...args)//扩展运算符
       delete context[fnName ]
       return res
}
//使用:
sayYourName.myApply(user,['hello'])

bind

  1. bind 方法将创建并返回一个新的函数,新函数称为绑定函数,并且绑定函数包裹着原始函数
  2. 在执行时,会显示的将原始函数内部的this指向context
  3. 除context外,所有剩余参数将全部传递给原始函数function
  4. 执行绑定函数时,如果传递了参数,这些参数将全部传递给原始函数 function
  5. 如果使用了new运算符调用生成的绑定函数,则忽略context
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值