前端面试之道

call 和 apply 和 bind

  1. 首先会问call 和 apply 和 bind 三者有什么区别?

这个区别应该很容易,如果回答不好,就不会继续下去了,如果回答正确,就会要求手写call函数

如果实现了call函数,apply和bind基本都没啥问题了,所谓首先来实现call函数

call的难点在哪里呢?

就是如何确定this的指向,其实这里很简单,就是判断一下,如果没有传入,则设置为window,如果有传入,则设置为传入的代码

Function.prototype.myCall = function(context{
 // 关键代码在这里,如果传入的context为空,则设置为window
  if (typeof context === undefined || typeof context === null) {
    context = window
  }
  const symbol = Symbol()
  context[symbol] = this
  const args = [...arguments].slice(1)
  const result = context[symbol](...args)
  delete context[symbol]
  return result
}

bind的实现有点类似call,但是这里因为bind会返回一个函数,假设返回的函数是A,需要考虑new A()的情况。

Function.prototype.myBind = function (context{
  if (typeof context === undefined || typeof context === null) {
    context = window
  }
  const _this = this
  const args = [...arguments].slice(1)
  // 返回一个函数
  return function F({
    // 因为返回了一个函数,我们可以这样使用 new F(),所以需要判断是否是按照new F()使用了。
    if (this instanceof F) {
      return new _this(...args, ...arguments)
    }
    // 这边的 apply 严谨点可以自己实现
    return _this.apply(context, args.concat(...arguments))
  }
}

new

new 的过程发生了什么?

  1. 新建一个对象
  2. 然后把设置的属性,挂载到对象上面。
  3. 设置对象的_proto_ 指向构造函数的原型链
  4. 构造函数调用apply,传入新建的对象,查看执行结果,如果结果是一个对象就返回,如果不是一个对象,就把第一步新建的对象返回。

既然分析清楚了实现方式,那么使用代码实现就比较清楚了

function create({
  // 新建一个对象
  const obj = {}
  let Con = [].shift.call(arguments)
  // 设置对象的_proto_ 指向构造函数的原型链
  obj.__proto__ = Con.prototype
  // 构造函数调用apply,传入新建的对象,查看执行结果,如果结果是一个对象就返回,如果不是一个对象,就把第一步新建的对象返回。
  let result = Con.apply(obj, arguments)
  return result instanceof Object ? result : obj
}

本文由 mdnice 多平台发布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值