实现一个函数判断数据类型
手写一个精确判断 JavaScript 数据类型的工具函数,支持所有常见数据类型的识别
问题
JavaScript 中的 typeof 操作符存在一些局限性,比如无法区分 null、数组、对象等类型。我们需要实现一个更精确的类型判断函数,能够准确识别所有 JavaScript 数据类型,包括基本类型和引用类型。
解答
/**
* 精确判断数据类型
* @param {*} value - 需要判断类型的值
* @returns {string} - 返回小写的类型字符串
*/
function getType(value) {
// 处理 null 的特殊情况
if (value === null) {
return 'null';
}
// 处理基本类型
const baseType = typeof value;
if (baseType !== 'object') {
return baseType;
}
// 处理引用类型,使用 Object.prototype.toString
const typeString = Object.prototype.toString.call(value);
// 提取类型名称,如 "[object Array]" => "array"
const type = typeString.slice(8, -1).toLowerCase();
return type;
}
/**
* 类型判断的便捷方法集合
*/
const typeUtils = {
isArray: (value) => getType(value) === 'array',
isObject: (value) => getType(value) === 'object',
isString: (value) => getType(value) === 'string',
isNumber: (value) => getType(value) === 'number',
isBoolean: (value) => getType(value) === 'boolean',
isFunction: (value) => getType(value) === 'function',
isNull: (value) => getType(value) === 'null',
isUndefined: (value) => getType(value) === 'undefined',
isSymbol: (value) => getType(value) === 'symbol',
isDate: (value) => getType(value) === 'date',
isRegExp: (value) => getType(value) === 'regexp',
isMap: (value) => getType(value) === 'map',
isSet: (value) => getType(value) === 'set',
isPromise: (value) => getType(value) === 'promise',
};
使用示例
// 基本类型
console.log(getType(123)); // "number"
console.log(getType('hello')); // "string"
console.log(getType(true)); // "boolean"
console.log(getType(undefined)); // "undefined"
console.log(getType(null)); // "null"
console.log(getType(Symbol('id'))); // "symbol"
console.log(getType(100n)); // "bigint"
// 引用类型
console.log(getType([])); // "array"
console.log(getType({})); // "object"
console.log(getType(function(){})); // "function"
console.log(getType(new Date())); // "date"
console.log(getType(/regex/)); // "regexp"
console.log(getType(new Map())); // "map"
console.log(getType(new Set())); // "set"
console.log(getType(Promise.resolve()));// "promise"
console.log(getType(new Error())); // "error"
// 使用便捷方法
console.log(typeUtils.isArray([1, 2, 3])); // true
console.log(typeUtils.isObject({})); // true
console.log(typeUtils.isNull(null)); // true
console.log(typeUtils.isDate(new Date())); // true
console.log(typeUtils.isPromise(Promise.resolve())); // true
// 实际应用场景
function processData(data) {
if (typeUtils.isArray(data)) {
return data.map(item => item * 2);
} else if (typeUtils.isObject(data)) {
return Object.keys(data).length;
} else if (typeUtils.isString(data)) {
return data.toUpperCase();
}
return data;
}
console.log(processData([1, 2, 3])); // [2, 4, 6]
console.log(processData({a: 1, b: 2})); // 2
console.log(processData('hello')); // "HELLO"
关键点
-
Object.prototype.toString.call() - 这是最可靠的类型判断方法,返回格式为
[object Type]的字符串,能准确识别所有内置类型 -
null 的特殊处理 -
typeof null返回"object"是 JavaScript 的历史遗留问题,需要单独判断 -
字符串处理技巧 - 使用
slice(8, -1)提取类型名称,去掉[object和]部分,并转为小写统一格式 -
性能优化 - 对于基本类型优先使用
typeof,只有引用类型才使用Object.prototype.toString,提高判断效率 -
扩展性设计 - 提供
typeUtils工具集,封装常用的类型判断方法,使用更便捷,代码更语义化 -
兼容性好 - 该方法兼容所有现代浏览器和 Node.js 环境,是业界公认的最佳实践
目录