index.js
  1  var toString = Object.prototype.toString;
  2  
  3  /**
  4   * Get the native `typeof` a value.
  5   *
  6   * @param  {*} `val`
  7   * @return {*} Native javascript type
  8   */
  9  
 10  module.exports = function kindOf(val) {
 11    var type = typeof val;
 12  
 13    // primitivies
 14    if (type === 'undefined') {
 15      return 'undefined';
 16    }
 17    if (val === null) {
 18      return 'null';
 19    }
 20    if (val === true || val === false || val instanceof Boolean) {
 21      return 'boolean';
 22    }
 23    if (type === 'string' || val instanceof String) {
 24      return 'string';
 25    }
 26    if (type === 'number' || val instanceof Number) {
 27      return 'number';
 28    }
 29  
 30    // functions
 31    if (type === 'function' || val instanceof Function) {
 32      if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') {
 33        return 'generatorfunction';
 34      }
 35      return 'function';
 36    }
 37  
 38    // array
 39    if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
 40      return 'array';
 41    }
 42  
 43    // check for instances of RegExp and Date before calling `toString`
 44    if (val instanceof RegExp) {
 45      return 'regexp';
 46    }
 47    if (val instanceof Date) {
 48      return 'date';
 49    }
 50  
 51    // other objects
 52    type = toString.call(val);
 53  
 54    if (type === '[object RegExp]') {
 55      return 'regexp';
 56    }
 57    if (type === '[object Date]') {
 58      return 'date';
 59    }
 60    if (type === '[object Arguments]') {
 61      return 'arguments';
 62    }
 63    if (type === '[object Error]') {
 64      return 'error';
 65    }
 66    if (type === '[object Promise]') {
 67      return 'promise';
 68    }
 69  
 70    // buffer
 71    if (isBuffer(val)) {
 72      return 'buffer';
 73    }
 74  
 75    // es6: Map, WeakMap, Set, WeakSet
 76    if (type === '[object Set]') {
 77      return 'set';
 78    }
 79    if (type === '[object WeakSet]') {
 80      return 'weakset';
 81    }
 82    if (type === '[object Map]') {
 83      return 'map';
 84    }
 85    if (type === '[object WeakMap]') {
 86      return 'weakmap';
 87    }
 88    if (type === '[object Symbol]') {
 89      return 'symbol';
 90    }
 91    
 92    if (type === '[object Map Iterator]') {
 93      return 'mapiterator';
 94    }
 95    if (type === '[object Set Iterator]') {
 96      return 'setiterator';
 97    }
 98    if (type === '[object String Iterator]') {
 99      return 'stringiterator';
100    }
101    if (type === '[object Array Iterator]') {
102      return 'arrayiterator';
103    }
104    
105    // typed arrays
106    if (type === '[object Int8Array]') {
107      return 'int8array';
108    }
109    if (type === '[object Uint8Array]') {
110      return 'uint8array';
111    }
112    if (type === '[object Uint8ClampedArray]') {
113      return 'uint8clampedarray';
114    }
115    if (type === '[object Int16Array]') {
116      return 'int16array';
117    }
118    if (type === '[object Uint16Array]') {
119      return 'uint16array';
120    }
121    if (type === '[object Int32Array]') {
122      return 'int32array';
123    }
124    if (type === '[object Uint32Array]') {
125      return 'uint32array';
126    }
127    if (type === '[object Float32Array]') {
128      return 'float32array';
129    }
130    if (type === '[object Float64Array]') {
131      return 'float64array';
132    }
133  
134    // must be a plain object
135    return 'object';
136  };
137  
138  /**
139   * If you need to support Safari 5-7 (8-10 yr-old browser),
140   * take a look at https://github.com/feross/is-buffer
141   */
142  
143  function isBuffer(val) {
144    return val.constructor
145      && typeof val.constructor.isBuffer === 'function'
146      && val.constructor.isBuffer(val);
147  }