Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一步一步手动实现一个 bind #72

Open
lovelmh13 opened this issue Jun 12, 2021 · 0 comments
Open

一步一步手动实现一个 bind #72

lovelmh13 opened this issue Jun 12, 2021 · 0 comments

Comments

@lovelmh13
Copy link
Owner

lovelmh13 commented Jun 12, 2021

bind 实现

最菜鸡的实现

Function.prototype.myBind = funciton (that) {
	const _this = this
  
  return function (){
    return this.call(that)
  }
}

增加参数

Function.prototype.myBind = funciton (that) {
	const _this = this
  const arg = Array.prototype.slice.call(arguments) // 把 arguments 从类数组转换成数组, 类似的时候还有 Array.from, [...arguments]
  return function (){
    return this.apply(that, arg.slice(1))
  }
}

验证:

const foo = {
	a: 1
}

function bar() {
  console.log(this.a)
}
// const a = bar.bind(foo)
// a()
const a = bar.myBind(foo, 'a', 'b', 'c')
a()

进阶一下,实现 bind 的预设参数功

Function.prototype.myBind2 = function (that) {
  const _this = this
  const argsArr = Array.prototype.slice.call(arguments, 1)

  return function () {
    const newArgs = Array.prototype.slice.call(arguments) // 新传递进来的
    const finalArgs = argsArr.concat(newArgs)
    return _this.apply(that, finalArgs)
  }
}

验证:

function list() {
  return Array.prototype.slice.call(arguments)
}

function addArguments(arg1, arg2) {
  return arg1 + arg2
}

const list1 = list(1, 2, 3)
const result1 = addArguments(1, 2) // 3
const result2 = addArguments(1, 3) // 4
console.log(result1)
console.log(result2)

const leadingThirtysevenList = list.myBind2(null, 37)
const addThirtySeven = addArguments.myBind2(null, 37)
const list2 = leadingThirtysevenList()
console.log(list2) // [37]

const list3 = leadingThirtysevenList(1, 2, 3)
console.log(list3) // [37, 1, 2, 3] 存住了之前的 37 那个预设

const result3 = addThirtySeven(5)
console.log(result3) // 37 + 5 = 42 存住了之前的 37 那个预设

const result4 = addThirtySeven(5, 1000)
console.log(result4) // 37 + 5 = 42 存住了之前的 37 那个预设, 忽略了第二个参数,因为到 addArguments 里的时候,已经没有把 1000 传进去了

更进一步,保证 bind 返回的函数,被当作构造函数时,this 仍然指向 函数本身

const Foo = fn.bind(that)

如果执行 new Foo() 的话,由于 new 具有最高的优先级,所以指向的 this 就不是 bind 绑定的 that,而是 Foo 本身。

如果执行的是 Foo() 的话,this 就是之前被 bindthat

Function.prototype.myBind3 = function (that) {
 	const _this = this
  const argsArr = Array.prototype.slice.call(arguments, 1)
  
  function bound () {
    const newArg = Array.prototype.slice.call(arguments) // 新传递进来的
    const finallyArg = argsArr.concat(newArg)
    return _this.apply(this instanceof F ? this : that || this, finallyArg) // 如果是 new bound,则 this 就是指向 bound 本身的,就不能被绑定成 that
	}
  const F = function () {}
  F.prototype = _this.prototype // 维护原型关系
  bound.prototype = new F() // 这个是重点,用来判断执行 bound 时,是否使用了 new, this instanceof F
  return bound
}

测试:

const foo = {
  a: 0
}

function Bar(b) {
  this.b = b
  console.log('this: ', this)
  console.log('this.a: ', this.a)
  console.log('this.b: ', this.b)
}

const B1 = Bar.myBind3(foo, 1)
const b11 = new B1() // 使用 new 来实例化 bind 后的函数,new 的优先级最高,this 指向 B1 构造函数本身
console.log(b11)
console.log('上 new ------------ 下 不new')
const b12 = B1()
console.log(b12)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant