index.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. 'use strict';
  2. var fnToStr = Function.prototype.toString;
  3. var reflectApply = typeof Reflect === 'object' && Reflect !== null && Reflect.apply;
  4. var badArrayLike;
  5. var isCallableMarker;
  6. if (typeof reflectApply === 'function' && typeof Object.defineProperty === 'function') {
  7. try {
  8. badArrayLike = Object.defineProperty({}, 'length', {
  9. get: function () {
  10. throw isCallableMarker;
  11. }
  12. });
  13. isCallableMarker = {};
  14. } catch (_) {
  15. reflectApply = null;
  16. }
  17. } else {
  18. reflectApply = null;
  19. }
  20. var constructorRegex = /^\s*class\b/;
  21. var isES6ClassFn = function isES6ClassFunction(value) {
  22. try {
  23. var fnStr = fnToStr.call(value);
  24. return constructorRegex.test(fnStr);
  25. } catch (e) {
  26. return false; // not a function
  27. }
  28. };
  29. var tryFunctionObject = function tryFunctionToStr(value) {
  30. try {
  31. if (isES6ClassFn(value)) { return false; }
  32. fnToStr.call(value);
  33. return true;
  34. } catch (e) {
  35. return false;
  36. }
  37. };
  38. var toStr = Object.prototype.toString;
  39. var fnClass = '[object Function]';
  40. var genClass = '[object GeneratorFunction]';
  41. var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
  42. module.exports = reflectApply
  43. ? function isCallable(value) {
  44. if (!value) { return false; }
  45. if (typeof value !== 'function' && typeof value !== 'object') { return false; }
  46. if (typeof value === 'function' && !value.prototype) { return true; }
  47. try {
  48. reflectApply(value, null, badArrayLike);
  49. } catch (e) {
  50. if (e !== isCallableMarker) { return false; }
  51. }
  52. return !isES6ClassFn(value);
  53. }
  54. : function isCallable(value) {
  55. if (!value) { return false; }
  56. if (typeof value !== 'function' && typeof value !== 'object') { return false; }
  57. if (typeof value === 'function' && !value.prototype) { return true; }
  58. if (hasToStringTag) { return tryFunctionObject(value); }
  59. if (isES6ClassFn(value)) { return false; }
  60. var strClass = toStr.call(value);
  61. return strClass === fnClass || strClass === genClass;
  62. };