JavaScript 如何准确判断数据类型?5 种方法深度对比
在写js的时候,很容易因为数据类型没判断好而出错,比如这样的代码:
function calculate(a, b) {
return a + b;
}
// 我以为是 10 + 20 = 30
calculate(10, 20); // 结果 30 对的
// 实际上用户输入的是字符串和数字
calculate("10", 20); // 结果为 "1020"
所以为了避免这种情况的出现,我们还是要去判断好数据类型。
在JavaScript中,有几种方式来判断数据类型,以下是常用的方法:
1. typeof 操作符
最常用的类型判断方法,但有一些局限性:
typeof 42; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" (历史遗留问题)
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"
typeof Symbol(); // "symbol"
typeof 42n; // "bigint"
局限性:
- 无法区分数组、对象和
null - 函数返回
function -
typeof适合判断基本类型,但遇到对象类型就力不从心了
2. instanceof 操作符
用于检测构造函数的 prototype 属性是否出现在对象的原型链中:
[] instanceof Array; // true
{} instanceof Object; // true
new Date() instanceof Date; // true
function(){} instanceof Function; // true
// 继承关系,数组也是对象
[] instanceof Object; // true
instanceof 的局限性:
// 基本类型用不了
42 instanceof Number; // false
"hello" instanceof String; // false
在跨 iframe 或不同 window 环境下可能失效(因为构造函数不同)
3. Object.prototype .toString.call()
这是最准确、最可靠的方法,能识别所有内置类型!
Object.prototype.toString.call(42); // "[object Number]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call(function(){}); // "[object Function]"
Object.prototype.toString.call(Symbol()); // "[object Symbol]"
Object.prototype.toString.call(42n); // "[object BigInt]"
我们封装一个实用的工具函数:
function getRealType(value) {
return Object.prototype.toString.call(value)
.slice(8, -1) // 截取"[object "和"]"之间的内容
.toLowerCase(); // 转为小写,更友好
}
console.log(getRealType([])); // "array"
console.log(getRealType(null)); // "null"
console.log(getRealType({})); // "object"
console.log(getRealType(new Date())); // "date"
4. 专用方法
对于一些特殊类型,JavaScript提供了专门的判断方法:
判断数组:Array.isArray()
Array.isArray([]); // true
Array.isArray({}); // false
Array.isArray("123"); // false
判断NaN:Number.isNaN()
// 注意区别!
isNaN("hello"); // true ← 字符串不是数字,但这样判断容易误解
Number.isNaN("hello"); // false ← 更准确:只有真正的NaN才返回true
Number.isNaN(NaN); // true
判断有限数字:Number.isFinite()
Number.isFinite(42); // true
Number.isFinite(Infinity); // false ← 无穷大不是有限数字
Number.isFinite("42"); // false ← 字符串不是数字
编写健壮的函数
在实际开发中的应用:
场景1:安全的数字相加
function safeAdd(a, b) {
// 确保两个参数都是数字类型
if (typeof a !== 'number' || typeof b !== 'number') {
throw new Error('参数必须是数字');
}
return a + b;
}
safeAdd(1, 2); // 3
safeAdd(1, "2"); // 报错:参数必须是数字
场景2:处理多种数据类型
function processData(data) {
// getRealType方法在第3点Object.prototype.toString.call()中有写
const type = getRealType(data);
switch(type) {
case 'array':
return data.map(item => item * 2);
case 'object':
return Object.keys(data).length;
case 'string':
return data.toUpperCase();
case 'number':
return data * 2;
default:
return '不支持的数据类型';
}
}
console.log(processData([1, 2, 3])); // [2, 4, 6]
console.log(processData("hello")); // "HELLO"
console.log(processData({a: 1, b: 2})); // 2
总结:选择合适的方法
| 场景 | 推荐方法 | 示例 |
|---|---|---|
| 判断基本类型 | typeof |
typeof "hello" === "string" |
| 判断数组 | Array.isArray() |
Array.isArray([]) |
| 判断自定义对象 | instanceof |
obj instanceof MyClass |
| 精确类型判断 | Object.prototype.toString.call() |
见上文工具函数 |
| 特殊值判断 | 专用方法 |
Number.isNaN(), Number.isFinite()
|
本文首发于公众号:程序员大华,专注分享前后端开发的实战笔记。关注我,少走弯路,一起进步!