hand-write function

71 阅读2分钟

1. apply-call-bind

1.1 基础版本

function foo(name, age) {
        console.log(this, name, age)
      }

      Function.prototype.hyapply = function (thisArg) {
        // this -> 调用的函数对象
        // thisArg -> 传入的第一个参数,要绑定的this
        // console.log(this) // 当前调用的函数对象
        // this.apply(thisArg)

        // 1. 获取thisArg,并且确保是一个对象类型
        thisArg = thisArg === null || thisArg === undefined ? window : Object(thisArg)

        // thisArg.fn = this
        Object.defineProperty(thisArg, 'fn', {
          enumerable: false,
          configurable: true,
          value: this
        })
        thisArg.fn()

        delete thisArg.fn
      }

      foo.hyapply({ name: 'why' }, ['james', 25])
      foo.hyapply(123, ['why', 18])
      foo.hyapply(null, ['kobe', 30])

      Function.prototype.hycall = function (...thisArg) {
        // this -> 调用的函数对象
        // thisArg -> 传入的第一个参数,要绑定的this
        // console.log(this) // 当前调用的函数对象
        // this.apply(thisArg)

        // 1. 获取thisArg,并且确保是一个对象类型
        thisArg = thisArg === null || thisArg === undefined ? window : Object(thisArg)

        // thisArg.fn = this
        Object.defineProperty(thisArg, 'fn', {
          enumerable: false,
          configurable: true,
          value: this
        })
        thisArg.fn()

        delete thisArg.fn
      }

      foo.hyapply({ name: 'why' }, 'james', 25)
      foo.hyapply(123, 'why', 18)
      foo.hyapply(null, 'kobe', 30)

1.2 函数封装

function foo(name, age) {
  console.log(this, name, age)
}

// 1. 封装思想
// 1.1 封装到独立的函数中
function execFn(thisArg, otherArgs, fn) {
  // 1. 获取thisArg,并且确保是一个对象类型
  thisArg = thisArg === null || thisArg === undefined ? window : Object(thisArg)

  // thisArg.fn = this
  Object.defineProperty(thisArg, 'fn', {
    enumerable: false,
    configurable: true,
    value: fn
  })
  thisArg.fn(...otherArgs)

  delete thisArg.fn
}
// Function.prototype.exec = function
Function.prototype.hyapply = function (thisArg, otherArgs) {
  execFn(thisArg, otherArgs, this)
}

foo.hyapply({ name: 'why' }, ['james', 25])
foo.hyapply(123, ['why', 18])
foo.hyapply(null, ['kobe', 30])

Function.prototype.hycall = function (thisArg, ...otherArgs) {
  execFn(thisArg, otherArgs, this)
}

foo.hycall({ name: 'why' }, 'james', 25)
foo.hycall(123, 'why', 18)
foo.hycall(null, 'kobe', 30)

1.3 封装到原型链上

function foo(name, age) {
  console.log(this, name, age)
}

// 1. 封装思想
// 1.1 封装到独立的函数中
Function.prototype.hyexec = function (thisArg, otherArgs) {
  // 1. 获取thisArg,并且确保是一个对象类型
  thisArg = thisArg === null || thisArg === undefined ? window : Object(thisArg)

  // thisArg.fn = this
  Object.defineProperty(thisArg, 'fn', {
    enumerable: false,
    configurable: true,
    value: this
  })
  thisArg.fn(...otherArgs)

  delete thisArg.fn
}
// Function.prototype.exec = function
Function.prototype.hyapply = function (thisArg, otherArgs) {
  this.hyexec(thisArg, otherArgs)
}

foo.hyapply({ name: 'why' }, ['james', 25])
foo.hyapply(123, ['why', 18])
foo.hyapply(null, ['kobe', 30])

Function.prototype.hycall = function (thisArg, ...otherArgs) {
  this.hyexec(thisArg, otherArgs)
}

foo.hycall({ name: 'why' }, 'james', 25)
foo.hycall(123, 'why', 18)
foo.hycall(null, 'kobe', 30)

1.4 bind

function foo(name, age, height, address) {
  console.log(this, name, age, height, address)
}

// Function prototype
// var newFn = foo.bind({ name: 'lwz' }, 'why', 18)
// newFn(1.88)

// hand-write bind
Function.prototype.hybind = function (thisArg, ...otherArgs) {
  thisArg = thisArg === null || thisArg === undefined ? window : thisArg
  Object.defineProperty(thisArg, 'fn', {
    configurable: true,
    enumerable: false,
    writable: false,
    value: this
  })
  return (...newArgs) => {
    var allArgs = [...otherArgs, ...newArgs]
    thisArg.fn(...allArgs)
  }
}

var newFn = foo.hybind({ name: 'lwz' }, 'why', 18)
newFn(1.88, '北京市')