implementation.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
  2. var slice = Array.prototype.slice;
  3. var toStr = Object.prototype.toString;
  4. var funcType = '[object Function]';
  5. module.exports = function bind(that) {
  6. var target = this;
  7. if (typeof target !== 'function' || toStr.call(target) !== funcType) {
  8. throw new TypeError(ERROR_MESSAGE + target);
  9. }
  10. var args = slice.call(arguments, 1);
  11. var bound;
  12. var binder = function () {
  13. if (this instanceof bound) {
  14. var result = target.apply(
  15. this,
  16. args.concat(slice.call(arguments))
  17. );
  18. if (Object(result) === result) {
  19. return result;
  20. }
  21. return this;
  22. } else {
  23. return target.apply(
  24. that,
  25. args.concat(slice.call(arguments))
  26. );
  27. }
  28. };
  29. var boundLength = Math.max(0, target.length - args.length);
  30. var boundArgs = [];
  31. for (var i = 0; i < boundLength; i++) {
  32. boundArgs.push('$' + i);
  33. }
  34. bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
  35. if (target.prototype) {
  36. var Empty = function Empty() {};
  37. Empty.prototype = target.prototype;
  38. bound.prototype = new Empty();
  39. Empty.prototype = null;
  40. }
  41. return bound;
  42. };