call和bind的原生实现

原生call的实现方法

原理:

当调用call时,call方法中的this就是调用体(也就是调用call的函数)

此时只需要将this赋值给传进来的对象,作为对象的方法进行调用,这样这个方法的this便会指向目标对象。当传进来的对象为null的时候,直接赋值为window

参数问题,,利用自带的arguments解决

代码

function person(a,b,c,d){
  console.log('name is '+this.name)
  console.log(a,b,c,d)
  return {
    a:11,
    b:12
  }
}
let jack = {
  name:'jack'
}
// 重写函数的call方法
Function.prototype.newCall=function (obj){
  // 当obj为null的时候指向window
  obj = obj || window
  // 获取除第一个以外的参数
  let arg = []
  for(let i = 1;i < arguments.length;i++){
    arg.push(arguments[i])
  }
  // 此处的this是调用体,在这里是person函数
  obj.b = this
  // 使用obj调用函数,使得被调用的函数的值指向obj
  // 保留函数原来的返回值
  const result = obj.b(...arg)
  delete obj.b
  return result
}
// 调用试一下
let result = person.newCall(jack,'father','mother','sister','brother')
console.log(result)

原生js实现bind

原理

调用bind时会返回一个函数,掉用函数时会改变this指向,获取this值,调用apply改变this指向

Function.prototype.newBind=function(obj){
  const arg1 = Array.prototype.slice.call(arguments,1)
  const that = this
  return  function(){
    const arg2 = Array.prototype.slice.call(arguments)
    return that.apply(obj,arg1.concat(arg2))
  }
}

比较麻烦的是这个new操作,会改变this指向

如下

function showName(a,b){
  console.log(this.name)
  console.log(a,b)
}
let obj = {
  name:'第一个'
}
let result = showName.bind(obj,'参数1','参数2')
result()	// "第一个" "参数1" "参数2"
let typeResult = new result() 	//undefined "参数1" "参数2"

故而需要进行如下修改

  • 首先返回的函数应该是一个具名函数,这样可以明确调用时的this指向并实现原型链的继承

  • 在调用时,需要使用instanceof判定当前的this是不是与返回的函数相关联

Function.prototype.newBind=function(obj){
  const arg1 = Array.prototype.slice.call(arguments,1)
  const that = this
  let back = function(){
    const arg2 = Array.prototype.slice.call(arguments)
     if(this instanceof back){
           return that.apply(this,arg1.concat(arg2))
     }
    return that.apply(obj,arg1.concat(arg2))
  }
  // 返回的值的原型对象需要与调用它的函数原型进行关联
  back.prototype = Object.create(this.prototype)
  // 上述语句与此处异曲同工
  // function o(){}
  // o.prototype = this.prototype
  // back.prototype = new o()
  return back
}
posted @ 2021-06-01 21:27  Monday1997  阅读(93)  评论(0编辑  收藏  举报