欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaScript函数实现--call、apply、bind

程序员文章站 2022-07-14 14:27:52
...

1、call函数实现

Function.prototype.newCall = function(context, ...args) {
  if (typeof context === 'object') {
    context = context || window;
  } else {
    context = Object.create(null);
  }

  const fn = Symbol();
  context[fn] = this;
  const res = context[fn](...args);
  delete context[fn];
  return res;
};

2、apply 函数实现

Function.prototype.newApply = function(context, parameter) {
  if (typeof context === 'object') {
    context = context || window
  } else {
    context = Object.create(null)
  }
  let fn = Symbol()
  context[fn] = this
  context[fn](parameter);
  delete context[fn]
}

3、bind 函数实现

(1)简单版本,不支持 new 运算符操作

Function.prototype.bind = function(context, ...args) {
  // this 代表要绑定的函数
  const self = this;
  return function () {
    return self.call(context, ...args);
  }
};

(2)支持new操作

/**
 * 我们创建的每个函数都有一个 prototype 属性,这个属性是一个指针,指向一个对象,
 * 而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
 *
 * 无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性
 * 这个属性指向函数的原型对象,在默认情况下,所有的原型对象都会自动活儿一个 constructor 属性,这个属性包含一个指向 prototype 属性所在的函数的指针
 */


/**
 * bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一系列参数将会在传递的实参前传入作为他的参数
 * 注意点:
 *  (1) 返回一个函数
 *  (2) 参数传递
 *  (3) 作为构造函数:
 *      一个绑定函数也能使用 new 操作符创建对象:这种行为就像把原函数当成构造器。提供的 this 被忽略,同时调用时的参数被提供给模拟函数
 */

```javascript
Function.prototype.bind = function (context) {
  if (typeof this !== 'function') {
    throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
  }

  const self = this;
  const args = Array.prototype.slice.call(arguments, 1);
  const fNOP = function () {};

  const fBound = function () {
    self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
  };

  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();

  return fBound;
};
相关标签: call apply bind