首页 > 试题广场 >

自己实现一个bind函数

[问答题]

核心思路均是借助函数柯里化来实现,但是参考答案是错的,不要被误导

  • bind函数没有必要设定第二个形参
调用bind可以传递多个参数,第一个参数表示一个新的对象,剩下的就是真正想要传入函数的参数了。我们不确定真正想要向函数传入多少个参数,所以设定第二个形参毫无意义,直接借助[].slice.call(arguments, 1)就可以获取传入的剩余的参数。
  • 被返回的函数没有必要设定形参
调用bind最终会返回一个函数,参考答案用newArg表示 调用这个被返回的函数时,传入的参数,显然这是错误的,newArg最终只能对应实参列表的第一个参数!

解释一下,[].slice.call(arguments, 1)是什么意思

  1. arguments是函数的一个属性,它是一个伪数组,里面保存着调用函数时,传进去的参数,但由于它不是真实的数组,所以并不能使用数组原型上的方法,因此我们就可以先用一个空数组调用slice方法,然后将this转化为arguments就可以。
  2. 第二个参数1就表示获取除第一个参数外的剩余参数。
Function.prototype.bind = function (obj) {
  let that = this  /* this对应了调用bind的函数,就比如下面的person */
  let args = [].slice.call(arguments, 1) /* 获取调用bind函数时,除第一项外剩余的参数 */
  return function (){
    that.apply(obj, args.concat(...arguments)) /* 返回的函数依旧可以再次传递参数,将两个参数拼接起来 */
  }
}
写一段测试的代码:
var person = function (){
  console.log(this.name);
  console.log(arguments)
}

var obj = {
  name: 'Tom'
}

var bindFun = person.bind(obj, '456');  /* 空  什么都不打印 */
bindFun('111');  
/*
Tom
[Arguments] { '0': '456', '1': '111' }
*/ 

调用原生bind返回的函数,可以当作一个构造函数来new实例化对象,但是我们手写的bind函数,其this指向和原型链都存在问题,与原生bind实现效果存在一定的差异,具体解决方案理解起来比较复杂,可以参考这篇文章:【手写 call、apply,再用 “函数柯里化+寄生组合” 实现 bind】https://blog.csdn.net/qq_44647809/article/details/120784181


编辑于 2021-10-18 19:00:16 回复(0)
function bind(){ }
发表于 2021-03-29 10:10:52 回复(0)