[1-2] 数据类型检测 · typeof、instanceof、toString.call 等方式对比

所属板块:1. 数据类型与内存机制

记录日期:2026-03-xx

更新:根据实际使用补充

1. 四种常见类型检测方式对比

方法 适用场景 主要优点 主要缺陷 / 注意点 推荐指数
typeof 判断基本类型(除 null 外) 简单、速度快 typeof null === 'object'(历史遗留 Bug);无法区分 Object / Array / null 等 ★★☆☆☆
instanceof 判断引用类型是否属于某个构造函数 直观,结合原型链 跨 iframe / 不同上下文失效;基本类型直接报错;可被原型链篡改 ★★★☆☆
constructor 判断对象的构造函数 直接访问 constructor 属性 容易被修改(obj.constructor = xxx);null/undefined 无此属性 ★☆☆☆☆
Object.prototype.toString.call() 几乎所有内置类型的精确判断(终极方案) 最可靠、防篡改、区分所有内置对象 写法稍长;自定义类型返回 object Object ★★★★★

记住:日常开发中,优先用 Object.prototype.toString.call() 处理不确定来源的数据。

2. typeof 的常见表现(包含坑)

js 复制代码
console.log(typeof 123);          // "number"
console.log(typeof "abc");        // "string"
console.log(typeof true);         // "boolean"
console.log(typeof undefined);    // "undefined"
console.log(typeof Symbol());     // "symbol"
console.log(typeof 123n);         // "bigint"
console.log(typeof {});           // "object"
console.log(typeof []);           // "object"   ← 无法区分数组
console.log(typeof null);         // "object"   ← 经典历史 Bug
console.log(typeof function(){}); // "function" ← 唯一能区分函数的

注意:typeof 无法区分 null 和对象,也分不清普通对象与数组/Date/RegExp 等。

3. instanceof 的原理与局限

原理:顺着对象的 __proto__ 链向上找,直到找到指定构造函数的 prototype。

js 复制代码
[] instanceof Array;         // true
{} instanceof Object;        // true
new Date() instanceof Date;  // true

// 但有坑:
[] instanceof Object;        // true(因为 Array.prototype.__proto__ 指向 Object.prototype)
"str" instanceof String;     // false(基本类型不是对象实例)

跨上下文问题示例(iframe 中常见):

js 复制代码
// 主页面
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeArray = iframe.contentWindow.Array;

console.log([] instanceof iframeArray);  // false,即使看起来是数组

4. Object.prototype.toString.call() 用法(最推荐)

这是最可靠的方式,返回格式统一为 [object XXX]

js 复制代码
Object.prototype.toString.call(123);          // "[object Number]"
Object.prototype.toString.call("abc");        // "[object String]"
Object.prototype.toString.call(true);         // "[object Boolean]"
Object.prototype.toString.call(undefined);    // "[object Undefined]"
Object.prototype.toString.call(null);         // "[object Null]"     ← 正确区分 null
Object.prototype.toString.call({});           // "[object Object]"
Object.prototype.toString.call([]);           // "[object Array]"    ← 能区分数组
Object.prototype.toString.call(new Date());   // "[object Date]"
Object.prototype.toString.call(/abc/);        // "[object RegExp]"
Object.prototype.toString.call(new Map());    // "[object Map]"
Object.prototype.toString.call(function(){}); // "[object Function]"

封装一个常用工具函数(自己项目里可以直接复制):

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

console.log(getType(null));      // "null"
console.log(getType([]));        // "array"
console.log(getType(new Map())); // "map"

5. 小结 & 实际使用建议

  • 只需要区分基本类型 → 用 typeof 够了(但记得 null 的坑)
  • 需要精确区分内置对象(如 Array/Date/RegExp/Map 等)→ 必须用 Object.prototype.toString.call()
  • instanceof 适合判断"是否是某个类的实例"(如自定义类、Error),但不适合通用类型检测
  • 永远不要依赖 constructor(太容易被改)

下一篇文章会记录隐式类型转换的规则和经典例子(\[\] == !\[\] 之类)。

返回总目录:戳这里

相关推荐
Hilaku25 分钟前
为什么技术极强的前端,往往当不好前端 Team Leader?
前端·javascript·程序员
幸运小圣1 小时前
SSE 与 WebSocket 新手入门:前端实时通信完全指南【JavaScript】
前端·javascript·websocket
艾伦野鸽ggg1 小时前
25级开学 JS 考核题解
前端·javascript
meilindehuzi_a1 小时前
LangChain.js + Milvus 向量长期记忆实战:对话写入、语义检索与 RAG 增强
javascript·langchain·milvus
leoZ2311 小时前
2026-09-08-mysql-57-init-walkthrough
前端·javascript·数据库·vue.js·opencv·mysql·adb
艾伦野鸽ggg2 小时前
JavaScript 原型链与原型对象详解
javascript·原型模式
paopaokaka_luck2 小时前
非遗文物数字化系统(AI非遗问答、ONNX图像识别、协同过滤推荐、ECharts数据分析、非遗知识浏览与互动、文创商城订单闭环、文化活动报名签到、社区交流)
前端·javascript·vue.js·人工智能·数据分析·echarts
mONESY2 小时前
让大模型「听话」输出 JSON:LangChain OutputParser 结构化输出实战,从手写正则到 Zod Schema 四层进化
javascript
研☆香3 小时前
js中使用的正则表达式
开发语言·javascript·正则表达式
开开心心就好3 小时前
免费桌签打印工具,支持批量导入名字
前端·javascript·人工智能·docker·jupyter·智能手机·语音识别