一、bind

1、基本概念

**bind()** 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。 — MDN

2、手写实现

  1. // 第一种不支持使用new调用新创建的构造函数,而第二种支持
  2. // Does not work with `new (funcA.bind(thisArg, args))`
  3. if (!Function.prototype.bind) (function(){
  4. var slice = Array.prototype.slice;
  5. Function.prototype.bind = function() {
  6. var thatFunc = this, thatArg = arguments[0];
  7. var args = slice.call(arguments, 1);
  8. if (typeof thatFunc !== 'function') {
  9. // closest thing possible to the ECMAScript 5
  10. // internal IsCallable function
  11. throw new TypeError('Function.prototype.bind - ' +
  12. 'what is trying to be bound is not callable');
  13. }
  14. return function(){
  15. var funcArgs = args.concat(slice.call(arguments))
  16. return thatFunc.apply(thatArg, funcArgs);
  17. };
  18. };
  19. })();
  20. // Yes, it does work with `new (funcA.bind(thisArg, args))`
  21. if (!Function.prototype.bind) (function(){
  22. var ArrayPrototypeSlice = Array.prototype.slice;
  23. Function.prototype.bind = function(otherThis) {
  24. if (typeof this !== 'function') {
  25. // closest thing possible to the ECMAScript 5
  26. // internal IsCallable function
  27. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  28. }
  29. var baseArgs= ArrayPrototypeSlice.call(arguments, 1),
  30. baseArgsLength = baseArgs.length,
  31. fToBind = this,
  32. fNOP = function() {},
  33. fBound = function() {
  34. baseArgs.length = baseArgsLength; // reset to default base arguments
  35. baseArgs.push.apply(baseArgs, arguments);
  36. return fToBind.apply(
  37. fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
  38. );
  39. };
  40. if (this.prototype) {
  41. // Function.prototype doesn't have a prototype property
  42. fNOP.prototype = this.prototype;
  43. }
  44. fBound.prototype = new fNOP();
  45. return fBound;
  46. };
  47. })();

二、call

1、基本概念

**call()** 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

注意:该方法的语法和作用与 apply()方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。

2、手写实现

  1. Function.prototype.call = function(context = window, ...args) {
  2. if (typeof this !== 'function') {
  3. throw new TypeError('Type Error');
  4. }
  5. const fn = Symbol('fn');
  6. context[fn] = this;
  7. const res = context[fn](...args);
  8. delete context[fn];
  9. return res;
  10. }

三、aplly

1、基本概念

**apply()** 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

注意:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组

2、手写实现

  1. Function.prototype.apply = function(context = window, args) {
  2. if (typeof this !== 'function') {
  3. throw new TypeError('Type Error');
  4. }
  5. const fn = Symbol('fn');
  6. context[fn] = this;
  7. const res = context[fn](...args);
  8. delete context[fn];
  9. return res;
  10. }

参考链接