手写实现bind、call、apply

2019-08-14  本文已影响0人  chrisghb
var a = {
    value: 1
}
function getValue(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value)
}
getValue.myCall(a, 'yck', '24')
getValue.myApply(a, ['yck', '24'])
// 手动实现call
Function.prototype.myCall = function (context) {
  // 兼容传入null的情况(context接收的是传入的第一个参数a)
  var context = context || window
  // getValue.myCall调用时,将this代表的原函数getValue添加到目标对象context属性fn上,即context.fn = getValue
  context.fn = this
  // arguments对象并不是一个真正的数组,而是一个类数组对象
  // 将 context 第二个开始的参数取出来=>('yck', '24')
  var args = [...arguments].slice(1)
  // 执行属性方法,相对于a.fn('yck', '24')
  var result = context.fn(...args)
  // 删除 fn
  delete context.fn
  return result
}
// 手动实现apply
Function.prototype.myApply = function (context) {
  // 兼容传入null的情况(context接收的是传入的第一个参数a)
  var context = context || window
  // getValue.myCall调用时,将this代表的原函数getValue添加到目标对象context属性fn上,即context.fn = getValue
  context.fn = this
  var result
  // 如果存在第二个参数,就将第二个参数展开
  if (arguments[1]) {
    result = context.fn(...arguments[1])
  } else {
    result = context.fn()
  }
  // 删除 fn
  delete context.fn
  return result
}

bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。
函数柯里化:在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数 预置通用参数,供多次重复调用。

var a = {
  name : "Cherry",
  fn : function (x,y) {
    console.log( x + y)
  }
}

var b = a.fn
var c = b.myBind (a,1) 
c(5) // 6
// 手动实现bind
Function.prototype.myBind = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  var _this = this // this代表a.fn 
  var args = [...arguments].slice(1) // 参数1
  // 返回一个函数
  return function F() {
    // 如果this是F的实例
    if (this instanceof F) {
      return new _this(...args, ...arguments) //参数 1和5合并
    }
    return _this.apply(context, args.concat(...arguments))
  }
}
上一篇下一篇

猜你喜欢

热点阅读