在 JavaScript 中检查数据类型的完整指南
JavaScript 是一种不太完美的语言,比如 检查数据类型 没有提供直接的方法。
在 JavaScript 中,有8 种数据类型,主要有 3 种方法来检查给定值的类型。在这篇文章中,我将介绍它们是什么,何时使用它们,以及在我看来,哪一个是最好的。
- 在 JavaScript中没有内置的方法来检查数据类型
- 忘记
typeofandinstanceof,检查数据类型的最好方法是使用Object.prototype.toString
typeof 运算符
可能第一个想到的是 typeof ,它适用于 number, string, undefined, boolean, symbol , function。 但使用时需要注意一些陷阱。
- 这是一个已知的错误
typeof null === 'object'typeof null 的历史详细介绍了这个错误。 - 它不区分普通对象和其他内置对象,除了function
typeof []; // 'object'
typeof {}; // 'object'
typeof new Date(); // 'object'
typeof /foo/; // 'object'
instanceof 运算符
instanceof运算符检查对象的构造函数。换句话说,它检测给定的实例对象是哪个类创建的。
let Car = function () {};
let benz = new Car();
benz instanceof Car; // true
因此,instaceof 可以正确确定对象的类型,但 不能正确确定 原始类型。
[] instanceof Array // ✅ true
(() => {}) instanceof Function; // ✅ true
new Map() instanceof Map; // ✅ true
1 instanceof Number; // ❌ false
'foo' instanceof String; // ❌ false
此外,由于instanceof检查对象的构造函数,如果您在运行时修改对象的原型,instanceof检查的结果可能会改变:
const array = [];
array instanceof Array; // ✅ true
Object.setPrototypeOf(array, null);
array instanceof Array; // ❌ false
如您所见,单独使用 typeof 和 instanceof 都不是完美的,大多数时候人们必须结合这两种方法来进行类型检查。
Object.prototype.toString 方法
事实证明,还有第三种可以说是更好的方法来检查 JavaScript 中的数据类型
Object.prototype.toString 它是一个存在于 Object.prototype 上的方法,它返回一个字符串值,用于根据其描述一个对象Symbol.toStringTag。如果你看一下它的规范,你会发现它实际上是我们在检查数据类型时一直在寻找的包罗万象的解决方案。
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call(1); // "[object Number]"
Object.prototype.toString.call('1'); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(new String('string')); // "[object String]"
Object.prototype.toString.call(function () {}); // "[object Function]"
Object.prototype.toString.call(null); //"[object Null]"
Object.prototype.toString.call(undefined); //"[object Undefined]"
Object.prototype.toString.call(/123/g); //"[object RegExp]"
Object.prototype.toString.call(new Date()); //"[object Date]"
Object.prototype.toString.call([]); //"[object Array]"
Object.prototype.toString.call(document); //"[object HTMLDocument]"
Object.prototype.toString.call(window); //"[object Window]
通过使用一个regExp进行字符串处理,我们可以提出以下解决方案来解决所有情况:
function getType(obj) {
const lowerCaseTheFirstLetter = (str) => str[0].toLowerCase() + str.slice(1);
const type = typeof obj;
if (type !== 'object') {
return type;
}
return lowerCaseTheFirstLetter(
Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1')
);
}
getType([]); // "array"
getType('123'); // "string"
getType(null); // "null"
getType(undefined); // "undefined"
getType(); // "undefined"
getType(function () {}); // "function"
getType(/123/g); // "regExp"
getType(new Date()); // "date"
getType(new Map()); // "map"
getType(new Set()); // "set"
事实上,许多类型检查库也是使用的这种技术。