nfssuzukaze / Blog

0 stars 0 forks source link

bind 的模拟实现 #22

Open nfssuzukaze opened 3 years ago

nfssuzukaze commented 3 years ago

1. bind 的模拟实现

1.1 bind 的初步实现

Function.prototype.bind = Function.prototype.bind || function(bind_obj) {
  const self = this
  // 防止 this 失效
  const firstArg = Array.prototype.slice.call(arguments, 1)
  // 调用 bind 时传入的参数

  return function() {
    // 调用 bind 返回的函数
    const secondArg = Array.prototype.slice.call(arguments)
    // 调用 (bind 返回的函数) 时传入的参数
    return self.apply(bind_obj, firstArg.concat(secondArg))
  }

}

1.2 bind 的进一步实现

Function.prototype.bind = Function.prototype.bind || function(bind_obj) {
  const self = this
  // 防止 this 失效
  const firstArg = Array.prototype.slice.call(arguments, 1)
  // 调用 bind 时传入的参数

  function func() {
    const secondArg = Array.prototype.slice.call(arguments)
    // 调用 (bind 返回的函数) 时传入的参数
    return self.apply(this instanceof func ? this : bind_obj, firstArg.concat(secondArg))
  }

  func.prototype = Object.create(self.prototype)
  // 1. 用于判定是不是调用了 new(因为调用 new 时所创建的对象原型链上也存在构造函数的 prototype)
  // 2. 使得绑定后的函数可以获取原函数的原型链上属性
  return func
}

1.3 bind 的最终实现

Function.prototype.bind = Function.prototype.bind || function(bind_obj) {
  if (typeof bind_obj === 'function') {
    throw new Error('what is trying to be bound is not callable')
    // 如果被绑定的并不是对象, 而是函数, 则抛出错误
  }

  const self = this
  // 防止 this 失效
  const firstArg = Array.prototype.slice.call(arguments, 1)
  // 调用 bind 时传入的参数

  function func() {
    const secondArg = Array.prototype.slice.call(arguments)
    // 调用 (bind 返回的函数) 时传入的参数
    return self.apply(this instanceof func ? this : bind_obj, firstArg.concat(secondArg))
  }

  func.prototype = Object.create(self.prototype)
  // 1. 用于判定是不是调用了 new(因为调用 new 时所创建的对象原型链上也存在构造函数的 prototype)
  // 2. 使得绑定后的函数可以获取原函数的原型链上属性
  return func
}