跳到主要内容

JavaScript 类型判断详解:typeof、instanceof 与 Object.prototype.toString

· 阅读需 2 分钟
Apache王也道长
软件开发者与技术作者

JavaScript 的 typeof 适合判断基本类型,但它会把数组、普通对象以及 null 中的部分值都归为 object。需要更细致地区分内置对象时,可以使用 Object.prototype.toString.call

基本用法

const objectToString = Object.prototype.toString;

console.log(objectToString.call([123]));
// [object Array]

console.log(objectToString.call("123"));
// [object String]

console.log(objectToString.call({ a: "123" }));
// [object Object]

console.log(objectToString.call(/123/));
// [object RegExp]

console.log(objectToString.call(123));
// [object Number]

console.log(objectToString.call(undefined));
// [object Undefined]

console.log(objectToString.call(null));
// [object Null]

返回值格式通常为 [object Type],其中 Type 表示对象的类型标签。

封装类型判断函数

function getType(value) {
return Object.prototype.toString
.call(value)
.slice(8, -1)
.toLowerCase();
}

console.log(getType([])); // array
console.log(getType(new Date())); // date
console.log(getType(new Map())); // map
console.log(getType(new Set())); // set
console.log(getType(Promise.resolve())); // promise
console.log(getType(null)); // null

也可以生成指定类型的判断函数:

function isType(value, type) {
return Object.prototype.toString.call(value) ===
`[object ${type}]`;
}

console.log(isType([], "Array")); // true
console.log(isType(/abc/, "RegExp")); // true
console.log(isType(new Date(), "Date")); // true

与 typeof 对比

typeof "hello"; // string
typeof 123; // number
typeof true; // boolean
typeof undefined; // undefined
typeof Symbol(); // symbol
typeof 1n; // bigint
typeof function() {}; // function

typeof null; // object
typeof []; // object
typeof {}; // object

判断字符串、数字、布尔值、undefinedsymbolbigint 和函数时,typeof 最简单。

判断数组

只需要判断数组时,优先使用:

Array.isArray(value);

Array.isArray 语义明确,并且可以识别来自不同 iframe 或 realm 的数组。

instanceof 的特点

value instanceof Date;
value instanceof Error;
value instanceof MyClass;

instanceof 检查构造函数的 prototype 是否出现在对象原型链中,适合判断自定义类实例。但跨 iframe 时,两个环境中的构造函数并不是同一个对象,结果可能不符合预期。

注意 Symbol.toStringTag

对象可以通过 Symbol.toStringTag 自定义类型标签:

const value = {
[Symbol.toStringTag]: "Custom"
};

console.log(Object.prototype.toString.call(value));
// [object Custom]

因此 Object.prototype.toString.call 很实用,但它并不是不可伪造的安全校验。涉及安全边界时,还应验证对象结构、字段类型和数据来源。

本文阅读量:--

总访问量 -- · 访客数 --