index.js 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. 'use strict';
  2. var fnToStr = Function.prototype.toString;
  3. var constructorRegex = /^\s*class /;
  4. var isES6ClassFn = function isES6ClassFn(value) {
  5. try {
  6. var fnStr = fnToStr.call(value);
  7. var singleStripped = fnStr.replace(/\/\/.*\n/g, '');
  8. var multiStripped = singleStripped.replace(/\/\*[.\s\S]*\*\//g, '');
  9. var spaceStripped = multiStripped.replace(/\n/mg, ' ').replace(/ {2}/g, ' ');
  10. return constructorRegex.test(spaceStripped);
  11. } catch (e) {
  12. return false; // not a function
  13. }
  14. };
  15. var tryFunctionObject = function tryFunctionObject(value) {
  16. try {
  17. if (isES6ClassFn(value)) { return false; }
  18. fnToStr.call(value);
  19. return true;
  20. } catch (e) {
  21. return false;
  22. }
  23. };
  24. var toStr = Object.prototype.toString;
  25. var fnClass = '[object Function]';
  26. var genClass = '[object GeneratorFunction]';
  27. var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
  28. module.exports = function isCallable(value) {
  29. if (!value) { return false; }
  30. if (typeof value !== 'function' && typeof value !== 'object') { return false; }
  31. if (hasToStringTag) { return tryFunctionObject(value); }
  32. if (isES6ClassFn(value)) { return false; }
  33. var strClass = toStr.call(value);
  34. return strClass === fnClass || strClass === genClass;
  35. };