JS 进阶篇(二) 手动实现call apply bind

手动实现call

  1. call的使用

    let obj = {
    		key:'obj value'
    	}
    funciton getName(){
    	return this.name
    }
    console.log(getName.call(obj))
    
  2. 思考

     1.如何在obj里面调用getName?
     2.call方法是绑定在谁的身上?
    
  3. 解答
    第一个问题,需要在obj内部添加一个getName方法

    var obj = {
    	name:"obj name",
    	getName:function(){
    		return this.name;
    	}
    }
    
    console.log(obj.getName())
    
    

    第二个问题,getName身上没有call,它会去Function.prototype上面去找

     getName.prototype == Function.prototype
    
  4. 思路

     1.Function.prototype 身上绑定 mycall 方法
     2.调用getName.mycall时,给传进来的对象身上绑定getName方法
     3.调用一次,然后删除,把调用结果返回
    
  5. code

    const obj = {
      key:'obj value'
    }
    function getValue (para1,para2) {
      return this.key + '-'+para1+'-'+para2
    }
    Function.prototype.mycall = function (obj,para1,para2) {
      // console.log(this);// this 指向了调用它的对象 这里是[Function: getValue]
      let fnName = this.name // [Function: getValue] 函数原型上有name length 属性
      obj[fnName] = this  //  等同于   obj.getValue  = ()=>{this.key}
      let result = obj[fnName](para1,para2) 
      delete obj[fnName] //删除obj中的 getName方法 使得obj不受影响
      return result
    }
    console.log(getValue.mycall(obj, 'from', 'mycall'));
    

手动实现apply

同call,只是传参方法变化
code

const obj = {
  key:'obj value'
}
function getValue (para1,para2) {
  return this.key + '-'+para1+'-'+para2
}
Function.prototype.myapply = function (obj,args) {
  // console.log(this);// this 指向了调用它的对象 这里是[Function: getValue]
  let fnName = this.name // [Function: getValue] 函数原型上有name length 属性
  obj[fnName] = this  //  等同于   obj.getValue  = ()=>{this.key}
  let result = obj[fnName](...args) 
  delete obj[fnName] //删除obj中的 getName方法 使得obj不受影响
  return result
}
console.log(getValue.myapply(obj,['from','myapply']));

手动实现bind

  1. 借用call版本
const obj = {
  key:'obj value'
}
function getValue (para1,para2) {
  return this.key + '-'+para1+'-'+para2
}

Function.prototype.mybind=function(obj, para1, para2){
  const _this = this
  function inner (para1, para2) {
    return _this.call(obj,para1, para2)
  }
  return inner
}
const bindFn = getValue.mybind(obj)
console.log(bindFn('from','mybind'));
  1. 原始版本
const obj = {
  key:'obj value'
}
function getValue (para1,para2) {
  return this.key + '-'+para1+'-'+para2
}
getValue.prototype.show = function () {
  console.log('Dog');
}
Function.prototype.mybind = function (obj) {
  const _this = this
  let args = Array.prototype.slice.mycall(arguments, 1)
  function inner () {  //内部实现call方法
     let innerArgs = Array.prototype.slice.mycall(arguments)
    let finalArgs = args.concat(innerArgs)
    let fnName = _this.name
    obj[fnName] = _this
    let result = obj[fnName](...finalArgs)
    delete obj[fnName]
    return result
  }
   /**
   * 这里修正原型链(必须要的!)
   * inner 的原型 指向了 Function 
   * 但是 fn 的原型不一定指向了 Function (比如fn是个构造函数,或者它原型上有自己的自定义方法)
   * 所以 让inner 的原型 指向 fn的原型  
   */
  inner.prototype = Object.create(_this.prototype) //修正原型链
  return inner  //这里是一个闭包
}
const bindFn = getValue.mybind(obj)
console.log(bindFn('from','mybind'));
console.dir(bindFn.prototype.show());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值