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