【手撕原理】前端面试题 手写call、apply、bind方法

手写call 、apply 、bind方法

实现call方法思路

1.在Function原型上增加_call方法,接受两个参数。第一个参数为指定的this值,默认值为window;第二个参数使用剩余运算符展开,获取参数列表。

2.将函数this设置为context对象的属性,通过隐式绑定的方式调用函数,把context上的属性删了,并返回函数调用的返回值

  • 这里的原理是:this指向调用它的对象,这是是context调用,所以this指向了context。

  • 为什么要删除context上的属性。
    防止这个属性对context造成影响,而且这个属性本身也没有用啦,不用留着占内存。

实现apply方法思路

1.在Function原型上增加_apply方法,接受两个参数。第一个参数为指定的this值,默认值为window;第二个参数接受一个数组,默认值为空数组

2.将函数this设置为context对象的属性,通过隐式绑定的方式调用函数,把context上的属性删了,并返回函数调用的返回值

实现bind方法思路

bind方法的实现可以参考apply。bind和apply的区别在于,bind是返回一个绑定好的函数,apply是直接调用。那么实现也很简单,就是返回一个函数,里面执行了apply的操作而已。

不过有一个需要判断的点,因为返回新的函数,要考虑到使用new去调用,并且new的优先级比较高,所以需要判断new的调用,还有一个特点就是bind调用的时候可以传参,调用之后生成的新的函数也可以传参,效果是一样的,所以这一块也要做处理。

前面已实现了apply 和 call ,那么bind 直接调用apply 或者 call 会更加优雅。

Function.prototype._call = function (context = window, ...args) {
  // 判断调用对象
  if (typeof this !== 'function') {
    throw new TypeError('Error');
  }
  args = args ? args : []
  //创建独一无二属性,以免覆盖原属性
  const key = Symbol();
  context[key] = this;
  //通过隐式绑定的方式调用函数
  const result = context[key](...args);
  //删除添加的属性
  delete context[key];
  //返回函数调用的返回值
  return result;
};

// 第二个参数是数组
Function.prototype._apply = function (context = window, args = []) {
  // 判断调用对象
  if (typeof this !== 'function') {
    throw new TypeError('Error');
  }
  const key = Symbol();
  context[key] = this;
  //通过隐式绑定的方式调用函数
  const result = context[key](...args);
  //删除添加的属性
  delete context[key];
  //返回函数调用的返回值
  return result;
};

Function.prototype._bind = function (context, ...args) {
  if (typeof this !== 'function') {
    throw new TypeError('Error');
  }
  //返回一个绑定this的函数,我们需要在此保存this
  const fn = this;
  return function newFn(...newFnArgs) {
    if (this instanceof newFn) {
      return new fn(...args, ...newFnArgs)
    }
    return fn.apply(context, [...args, ...newFnArgs])
  }
};


let obj = { x: 1 };
function fn() {
  console.log(this.x, arguments);
}
fn._call(obj, 1, 2, 3);
fn._apply(obj, [1, 2, 3]);

const bindFn = fn._bind(obj, 1, 2, 3);
bindFn();

均输出1 [Arguments] { '0': 1, '1': 2, '2': 3 }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值