说明
该库是用于js类型判断的。
使用
const kindOf = require('kind-of');
kindOf(undefined);
//=> 'undefined'
kindOf(null);
//=> 'null'
kindOf(true);
//=> 'boolean'
kindOf(false);
//=> 'boolean'
kindOf(new Buffer(''));
//=> 'buffer'
kindOf(42);
//=> 'number'
kindOf('str');
//=> 'string'
kindOf(arguments);
//=> 'arguments'
kindOf({});
//=> 'object'
kindOf(Object.create(null));
//=> 'object'
kindOf(new Test());
//=> 'object'
kindOf(new Date());
//=> 'date'
kindOf([1, 2, 3]);
//=> 'array'
kindOf(/foo/);
//=> 'regexp'
kindOf(new RegExp('foo'));
//=> 'regexp'
kindOf(new Error('error'));
//=> 'error'
kindOf(function () {});
//=> 'function'
kindOf(function * () {});
//=> 'generatorfunction'
kindOf(Symbol('str'));
//=> 'symbol'
kindOf(new Map());
//=> 'map'
kindOf(new WeakMap());
//=> 'weakmap'
kindOf(new Set());
//=> 'set'
kindOf(new WeakSet());
//=> 'weakset'
kindOf(new Int8Array());
//=> 'int8array'
kindOf(new Uint8Array());
//=> 'uint8array'
kindOf(new Uint8ClampedArray());
//=> 'uint8clampedarray'
kindOf(new Int16Array());
//=> 'int16array'
kindOf(new Uint16Array());
//=> 'uint16array'
kindOf(new Int32Array());
//=> 'int32array'
kindOf(new Uint32Array());
//=> 'uint32array'
kindOf(new Float32Array());
//=> 'float32array'
kindOf(new Float64Array());
//=> 'float64array'
源码解读
值类型(基本类型)(7) :字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol、bigint。
引用数据类型(对象类型) :对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
基础类型
if (val === void 0) return 'undefined';
if (val === null) return 'null';
var type = typeof val;
// typeof 可以 undefined、string、boolean、number、symbol,bigint、function
if (type === 'boolean') return 'boolean';
if (type === 'string') return 'string';
if (type === 'number') return 'number';
if (type === 'symbol') return 'symbol';
if (type === 'bigint') return 'bigint';
function
函数分为普通函数与generator函数;
function ctorName(val) {
return typeof val.constructor === 'function' ? val.constructor.name : null;
}
function isGeneratorFn(name, val) {
return ctorName(name) === 'GeneratorFunction';
}
if (type === 'function') {
return isGeneratorFn(val) ? 'generatorfunction' : 'function';
}
generotor
var getGeneratorFunc = function () { // eslint-disable-line consistent-return
if (!hasToStringTag) {
return false;
}
try {
return Function('return function*() {}')();
} catch (e) {
}
};
var generatorFunc = getGeneratorFunc();
var GeneratorFunction = getProto && generatorFunc ? getProto(generatorFunc) : false;
var getProto = Object.getPrototypeOf;
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
var isFnRegex = /^\s*(?:function)?*/;
function isGeneratorFunction(fn) {
if (typeof fn !== 'function') {
return false;
}
// 方式1
if (isFnRegex.test(fnToStr.call(fn))) {
return true;
}
if (!hasToStringTag) {
var str = toStr.call(fn);
// 方式2
return str === '[object GeneratorFunction]';
}
// 方式3
return getProto && getProto(fn) === GeneratorFunction;
};
生成器
// 1.
function isGeneratorObj(val) {
return typeof val.throw === 'function'
&& typeof val.return === 'function'
&& typeof val.next === 'function';
}
// 2. Object.prototype.toString.call(g) '[object Generator]'
var gen = function* gen(){
try {
yield console.log('a');
} catch (e) {
// ...
}
yield console.log('b');
yield console.log('c');
}
var g = gen();
g.next() // a
g.throw() // b
g.next() // c
数组
function isArray(val) {
// 1.
if (Array.isArray) return Array.isArray(val);
//2.
return val instanceof Array;
}
//3.
[].constructor === Array
//4.
Object.prototype.toString.call([]) // '[object Array]'
arguments
// 1.
function isArguments(val) {
try {
if (typeof val.length === 'number' && typeof val.callee === 'function') {
return true;
}
} catch (err) {
if (err.message.indexOf('callee') !== -1) {
return true;
}
}
return false;
}
// 2.
function test(){
// [object Arguments]
console.log('kindOf(arguments)', Object.prototype.toString.call(arguments))
}
test()
Date
function isDate(val) {
// 1.
if (val instanceof Date) return true;
// 2.
return typeof val.toDateString === 'function'
&& typeof val.getDate === 'function'
&& typeof val.setDate === 'function';
}
// 3.
Object.prototype.toString.call(new Date) // '[object Date]'
// 4.
data = new Date()
data.constructor.name === 'Date'
Error
function isError(val) {
return
// 1.
val instanceof Error
// 2.
|| (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
}
// 3. Object.prototype.toString.call(err)
RegExp
function isRegexp(val) {
if (val instanceof RegExp) return true;
return typeof val.flags === 'string'
&& typeof val.ignoreCase === 'boolean'
&& typeof val.multiline === 'boolean'
&& typeof val.global === 'boolean';
}
// 3. Object.prototype.toString.call(/123/g) // '[object RegExp]'
constructor类型判断
function ctorName(val) {
return typeof val.constructor === 'function' ? val.constructor.name : null;
}
switch (ctorName(val)) {
case 'Symbol': return 'symbol';
case 'Promise': return 'promise';
// Set, Map, WeakSet, WeakMap
case 'WeakMap': return 'weakmap';
case 'WeakSet': return 'weakset';
case 'Map': return 'map';
case 'Set': return 'set';
// 8-bit typed arrays
case 'Int8Array': return 'int8array';
case 'Uint8Array': return 'uint8array';
case 'Uint8ClampedArray': return 'uint8clampedarray';
// 16-bit typed arrays
case 'Int16Array': return 'int16array';
case 'Uint16Array': return 'uint16array';
// 32-bit typed arrays
case 'Int32Array': return 'int32array';
case 'Uint32Array': return 'uint32array';
case 'Float32Array': return 'float32array';
case 'Float64Array': return 'float64array';
}
tostring类型判断
// Non-plain objects
type = toString.call(val);
switch (type) {
case '[object Object]': return 'object';
// iterators
case '[object Map Iterator]': return 'mapiterator';
case '[object Set Iterator]': return 'setiterator';
case '[object String Iterator]': return 'stringiterator';
case '[object Array Iterator]': return 'arrayiterator';
}
map = new Map()
Object.prototype.toString.call(map.keys()) // '[object Map Iterator]'
// other
return type.slice(8, -1).toLowerCase().replace(/\s/g, '');