Skip to content

实现bind方法

js
Function.prototype.myBind = function (context, ...args) {
  // 新建一个变量赋值this,表示当前函数
  const fn = this
  // 判断有没有参数传进来
  args = args ? args : []
  // 返回一个函数,并调用fn
  return function newFn(...newFnArgs) {
    if (this instanceof newFn) {
      return new fn(...args, ...newFnArgs)
    }
    return fn.apply(context, [...args, ...newFnArgs])
  }
}
js
// bind返回一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过new的方式调用
// 对于直接调用来说,这里选择了apply的方式实现,但是对于参数需要注意以下情况:因为bind可以试下类似的代码:f.bind(obj,1)(2),所以我们需要将两边的参数拼接起来
// new调用的话,不会被任何方式改变this,所以对于这种情况我们需要忽略传入的this

// 简洁版本
Function.prototype.myBind = function (context, ...outerArgs) {
  // this --> func     context --> obj   outerArgs --> [10,20]
  let self = this
  // 返回一个函数,...innerArgs为实际调用时传入的参数
  return function F(...innerArgs) {
    // 考虑new的方式
    if (self instanceof F) {
      return new self(...outerArgs, ...innerArgs)
    }
    // 把func执行,并且改变this即可,返回改变了this的函数,参数合并
    return self.apply(context, [...outerArgs, ...innerArgs])
  }
}
js
Function.prototype.myBind = function (context, ...args) {
  if (!context || context === null) {
    context = window
  }
  let fn = Symbol()
  context[fn] = this
  let _this = this
  const result = function (...innerArgs) {
    if (this instanceof _this === true) {
      this[fn] = _this
      this[fn](...[...args, ...innerArgs])
    } else {
      context[fn](...[...args, ...innerArgs])
    }
  }
  result.prototype = Object.create(this.prototype)
  return result
}

//用法如下

function Person(name, age) {
  console.log(name) //'我是参数传进来的name'
  console.log(age) //'我是参数传进来的age'
  console.log(this) //构造函数this指向实例对象
}
// 构造函数原型的方法
Person.prototype.say = function () {
  console.log(123)
}
let obj = {
  objName: '我是obj传进来的name',
  objAge: '我是obj传进来的age',
}
// 普通函数
function normalFun(name, age) {
  console.log(name) //'我是参数传进来的name'
  console.log(age) //'我是参数传进来的age'
  console.log(this) //普通函数this指向绑定bind的第一个参数 也就是例子中的obj
  console.log(this.objName) //'我是obj传进来的name'
  console.log(this.objAge) //'我是obj传进来的age'
}

//先测试作为构造函数调用
let bindFun1 = Person.myBind(obj, '我是参数传进来的name')
let a = new bindFun('我是参数传进来的age')
a.say() //123

//再测试作为普通函数调用
let bindFun2 = normalFun.myBind(obj, '我是参数传进来的name')
bindFun('我是参数传进来的age')
js
Function.prototype.myBind = function (context) {
  if (typeof this !== 'function') {
    throw new Error('Function.prototype.bind - what is trying to be bound is not callable')
  }
  var self = this
  var args = Array.prototype.slice.call(arguments, 1)
  var fNOP = function () {}
  var fBound = function () {
    var bindArgs = Array.prototype.slice.call(arguments)
    return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs))
  }
  fNOP.prototype = this.prototype
  fBound.prototype = new fNOP()
  return fBound
}

Function.prototype.bindFn = function bind(thisArg) {
  if (typeof this !== 'function') {
    throw new TypeError(this + 'must be function')
  }
  var self = this
  var args = [].slice.call(arguments, 1)
  var bound = function () {
    var boundArgs = [].slice.call(arguments)
    console.log(this, '#####################', self)
    return self.apply(thisArg, args.concat(boundArgs))
  }
  return bound
}
// 测试
var obj = {
  name: '若川',
}
function original(a, b) {
  console.log(this.name)
  console.log([a, b])
}
var bound = original.bindFn(obj, 1)
bound(2) // '若川', [1, 2]

Function.prototype.bindFn2 = function bind(thisArg) {
  if (typeof this !== 'function') {
    throw new TypeError(this + 'must be a function')
  }
  var self = this
  var args = [].slice.call(arguments, 1)
  var bound = function () {
    var boundArgs = [].slice.call(arguments)
    var finalArgs = args.concat(boundArgs)
    if (this instanceof bound) {
      if (self.prototype) {
        function Empty() {}
        Empty.prototype = self.prototype
        bound.prototype = new Empty()
      }
      var result = self.apply(this, finalArgs)
      var isObjet = typeof result === 'object' && result !== null
      var isFunction = typeof result === 'function'
      if (isObjet || isFunction) {
        return result
      }
      return this
    } else {
      return self.apply(thisArg, finalArgs)
    }
  }
  return bound
}

Function.prototype.bind =
  Function.prototype.bind ||
  function bind(thisArg) {
    if (typeof this !== 'function') {
      throw new TypeError(this + 'must be a function')
    }
    var self = this
    var args = [].slice.call(arguments, 1)
    var bound = function () {
      var boundArgs = [].slice.call(arguments)
      var finalArgs = args.concat(boundArgs)
      if (this instanceof bound) {
        if (self.prototype) {
          function Empty() {}
          Empty.prototype = self.prototype
          bound.prototype = new Empty()
        }
        var result = self.apply(this, finalArgs)
        var isObject = typeof result === 'object' && result !== null
        var isFunction = typeof result === 'function'
        if (isObject || isFunction) {
          return result
        }
        return this
      } else {
        return self.apply(thisArg, finalArgs)
      }
    }
  }

如有转载或 CV 的请标注本站原文地址