index.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. var toString = Object.prototype.toString;
  2. module.exports = function kindOf(val) {
  3. if (val === void 0) return 'undefined';
  4. if (val === null) return 'null';
  5. var type = typeof val;
  6. if (type === 'boolean') return 'boolean';
  7. if (type === 'string') return 'string';
  8. if (type === 'number') return 'number';
  9. if (type === 'symbol') return 'symbol';
  10. if (type === 'function') {
  11. return isGeneratorFn(val) ? 'generatorfunction' : 'function';
  12. }
  13. if (isArray(val)) return 'array';
  14. if (isBuffer(val)) return 'buffer';
  15. if (isArguments(val)) return 'arguments';
  16. if (isDate(val)) return 'date';
  17. if (isError(val)) return 'error';
  18. if (isRegexp(val)) return 'regexp';
  19. switch (ctorName(val)) {
  20. case 'Symbol': return 'symbol';
  21. case 'Promise': return 'promise';
  22. // Set, Map, WeakSet, WeakMap
  23. case 'WeakMap': return 'weakmap';
  24. case 'WeakSet': return 'weakset';
  25. case 'Map': return 'map';
  26. case 'Set': return 'set';
  27. // 8-bit typed arrays
  28. case 'Int8Array': return 'int8array';
  29. case 'Uint8Array': return 'uint8array';
  30. case 'Uint8ClampedArray': return 'uint8clampedarray';
  31. // 16-bit typed arrays
  32. case 'Int16Array': return 'int16array';
  33. case 'Uint16Array': return 'uint16array';
  34. // 32-bit typed arrays
  35. case 'Int32Array': return 'int32array';
  36. case 'Uint32Array': return 'uint32array';
  37. case 'Float32Array': return 'float32array';
  38. case 'Float64Array': return 'float64array';
  39. }
  40. if (isGeneratorObj(val)) {
  41. return 'generator';
  42. }
  43. // Non-plain objects
  44. type = toString.call(val);
  45. switch (type) {
  46. case '[object Object]': return 'object';
  47. // iterators
  48. case '[object Map Iterator]': return 'mapiterator';
  49. case '[object Set Iterator]': return 'setiterator';
  50. case '[object String Iterator]': return 'stringiterator';
  51. case '[object Array Iterator]': return 'arrayiterator';
  52. }
  53. // other
  54. return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
  55. };
  56. function ctorName(val) {
  57. return typeof val.constructor === 'function' ? val.constructor.name : null;
  58. }
  59. function isArray(val) {
  60. if (Array.isArray) return Array.isArray(val);
  61. return val instanceof Array;
  62. }
  63. function isError(val) {
  64. return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
  65. }
  66. function isDate(val) {
  67. if (val instanceof Date) return true;
  68. return typeof val.toDateString === 'function'
  69. && typeof val.getDate === 'function'
  70. && typeof val.setDate === 'function';
  71. }
  72. function isRegexp(val) {
  73. if (val instanceof RegExp) return true;
  74. return typeof val.flags === 'string'
  75. && typeof val.ignoreCase === 'boolean'
  76. && typeof val.multiline === 'boolean'
  77. && typeof val.global === 'boolean';
  78. }
  79. function isGeneratorFn(name, val) {
  80. return ctorName(name) === 'GeneratorFunction';
  81. }
  82. function isGeneratorObj(val) {
  83. return typeof val.throw === 'function'
  84. && typeof val.return === 'function'
  85. && typeof val.next === 'function';
  86. }
  87. function isArguments(val) {
  88. try {
  89. if (typeof val.length === 'number' && typeof val.callee === 'function') {
  90. return true;
  91. }
  92. } catch (err) {
  93. if (err.message.indexOf('callee') !== -1) {
  94. return true;
  95. }
  96. }
  97. return false;
  98. }
  99. /**
  100. * If you need to support Safari 5-7 (8-10 yr-old browser),
  101. * take a look at https://github.com/feross/is-buffer
  102. */
  103. function isBuffer(val) {
  104. if (val.constructor && typeof val.constructor.isBuffer === 'function') {
  105. return val.constructor.isBuffer(val);
  106. }
  107. return false;
  108. }