duyue6002 / Blog

:pencil2: Write here
http://duyue6002.github.io/Blog/#/
5 stars 1 forks source link

[总结] bind, apply, call 的使用及实现 #21

Open duyue6002 opened 5 years ago

duyue6002 commented 5 years ago

apply / call

区别

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2]);

参数数量固定时用call,不确定时用apply。希望改变上下文环境后立即执行,用apply / call

实现 apply

Function.prototype.myApply = function(context = window, arguments) {
  if (!context) {
    context = Object.create(null);
  }
  context.fn = this;
  if (arguments) {
    context.fn(...arguments);
  } else {
    context.fn();
  }
  delete context.fn;
};

实现 call

Function.prototype.myApply = function(context = window, ...arguments) {
  if (!context) {
    context = Object.create(null);
  }
  context.fn = this;
  if (arguments) {
    context.fn(...arguments);
  } else {
    context.fn();
  }
  delete context.fn;
};
duyue6002 commented 5 years ago

bind

传入想要的上下文obj,this会被设置为传入的obj,但是连续绑定多次是无效的。 当希望改变上下文环境后,回调执行时使用bind(),返回对应函数。

实现

Function.prototype.myBind = function(context = window) {
  if (!context) {
    context = Object.create(null);
  }
  let self = this;
  let args = [...arguments].slice(1);
  let fNOP = function () {};
  let bound = function() {
    // 当对象是被new创建的,这时绑定的应是对象本身,而非原闭包的bind绑定的对象。因为new操作符会将this指向新创建的对象
    return self.apply(this instanceof fNOP ? this : context, args.concat(...arguments));
  }
  // 维护原型
  fNOP.prototype = self.prototype;
  bound.prototype = new fNOP();
  return bound;
};