手撕call、apply和bind

124 阅读1分钟

call、apply和bind

call

Function.prototype.hyCall=function (thisArg,...arg) {
var fn = this     //拿到被执行的函数foo,因为通过foo.hyCall()调用所以可以拿到hyCall的this是foo函数本身
// fn.call(thisArg)     //简略方法 直接调用call
thisArg = (thisArg!==null&&thisArg!==undefined) ? Object(thisArg) : window    // 将输入的参数封装为对象,当绑定目标为null或者undefined时,不进行绑定
thisArg.fn=fn               //在传入对象中添加方法
let result = thisArg.fn(...arg)                //调用将fn(foo)中的this绑定到thisArg上
delete thisArg.fn
return result
​
}
​
function foo (sum1,sum2) {
    console.log('这是foo函数',this);
    return sum1+sum2
}
​
foo() 
foo.call()
foo.hyCall()

总结:先在函数的原型链上添加hyCall方法,再拿到foo函数(因为是通过foo.hycall,所以hycall内的this隐式绑定foo),再将hycall中的第一个形参包裹为对象,在这个对象中添加foo方法,使用thisArg.foo() 去调用foo从而使foo绑定到形参上

apply

Function.prototype.hyApply=function (thisArg,args) {
let fn = this
thisArg = (thisArg===null||thisArg===undefined) ? window : object(thisArg)
​
thisArg.fn = fn
​
args=args?args:[]  //判断args是否有值传入
result= thisArg.fn(...args)
delete thisArg.fn
return result
}
​
​
function foo (sum1,sum2) {
    console.log('这是foo的this:',this,);
return sum1+sum2
}
​
​
result = foo.hyApply('abc')
console.log(result);

bind

Function.prototype.hybind = 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
  }
​
  return proxyFn
}