← 返回题目列表

JavaScript 有哪些数据类型?如何判断类型?

高频 简单 第 3 / 29 题 更新于 2026/07/27
JavaScript数据类型typeofinstanceof

简化版

JavaScript 数据类型分为原始类型和引用类型。原始类型包括 stringnumberbooleanundefinednullsymbolbigint,引用类型主要是对象。判断类型常用 typeofinstanceofObject.prototype.toString.call()

详细版

typeof 适合判断大多数原始类型:

typeof 'a'; // 'string'
typeof 1; // 'number'
typeof undefined; // 'undefined'
typeof Symbol(); // 'symbol'

但它有两个常见坑:

typeof null; // 'object'
typeof []; // 'object'

instanceof 用于判断对象是否出现在某个构造函数的原型链上:

[] instanceof Array; // true

更通用的精确判断方式是:

Object.prototype.toString.call([]); // '[object Array]'
Object.prototype.toString.call(null); // '[object Null]'

面试回答要说明:类型判断没有一个 API 包打天下,要按场景选择。

完整版教学

一、原始类型和引用类型的区别

原始类型的值本身不可再拆分,变量保存的是值。引用类型保存的是对象引用,多个变量可能指向同一个对象。

let a = { count: 1 };
let b = a;
b.count = 2;
console.log(a.count); // 2

这不是“对象赋值会复制对象”,而是两个变量指向同一块对象数据。

二、typeof 为什么不能判断 null 和数组

typeof null === 'object' 是历史遗留问题,不能据此说 null 是对象。数组本质上是对象的一种特殊形式,所以 typeof [] 也是 'object'

因此 typeof 的合理使用范围是快速判断基本类型和函数:

typeof function () {}; // 'function'

三、instanceof 的边界

instanceof 依赖原型链。它适合判断自定义类实例,但跨 iframe、跨 realm 时可能失效,因为不同运行环境里的 Array 构造函数不是同一个。

value instanceof Array

在普通页面够用,但通用库更倾向 Array.isArray(value)

四、Object.prototype.toString 的优势

Object.prototype.toString.call(value) 会根据 null/undefined、内置对象品牌以及 Symbol.toStringTag 等规则形成标签,通常能区分数组、日期、正则、null、undefined 等。

它的缺点是写法稍长,实际项目里通常封装成工具函数。对象还能通过 Symbol.toStringTag 改变显示标签,所以它适合常规内置类型识别,却不应被误当成无法伪造的安全类型证明。

五、面试追问与工程落地

面试官常会追问“为什么 typeof null 是 object”。这不是规范认为 null 是对象,而是早期实现里类型标签遗留导致的历史 bug,因为兼容性原因一直保留。回答时要明确:null 是原始类型里的特殊值,表示空对象引用或空值意图,但它本身不是对象。

另一个追问是 Number.isNaN 和全局 isNaN 的区别。全局 isNaN 会先做类型转换,isNaN('abc') 是 true;Number.isNaN 不做隐式转换,只有真正的 NaN 才返回 true。类型判断题里能提到隐式转换,会显得更扎实。

工程里接口数据、表单输入、URL 参数都不要假设类型正确。后端返回的数字可能是字符串,空值可能是 null,也可能字段缺失。类型判断常常要和数据校验结合,尤其是涉及金额、权限、开关配置时。

六、把类型识别与相等语义分开

类型判断回答“值属于什么类别”,相等比较回答“两个值是否按某种规则相同”,不能混为一谈。例如 typeof NaN'number',但 NaN === NaNfalseObject.is(NaN, NaN)true。相反,0 === -0true,而 Object.is(0, -0)false

工具适合回答关键边界
typeof原始类型与可调用对象的快速分类null 返回 object,普通对象无法细分
Array.isArray是否为真正数组 exotic object跨 realm 仍可靠
instanceof构造器原型是否出现在对象链上可受 realm 与 Symbol.hasInstance 影响
Object.prototype.toString.call常见内置对象标签Symbol.toStringTag 可影响结果
Object.isSameValue 相等语义它不是类型检测 API
// 这里列出 7个不同语义的值
const values = [undefined, null, NaN, 0, -0, 1n, Symbol('x')];
values.map(value => typeof value);
// ['undefined', 'object', 'number', 'number', 'number', 'bigint', 'symbol']

ECMAScript 规范明确把 Null 定义为原始类型,同时规定 typeof null 返回字符串 'object'。面试中可以说这是兼容历史行为,但不要把未经规范证明的早期二进制标签故事当成唯一正式解释。

没有一个类型检测 API 能包办所有问题:先问要区分原始值、数组、类实例、跨 realm 内置对象,还是要做运行时数据校验。

七、常见误区与追问

  • 误区:typeof null === 'object' 说明 null 是对象。 Null 是独立原始类型,object 只是 typeof 运算符被规范保留的返回结果。
  • 误区:instanceof 只是比较对象的 constructor 属性。 默认算法检查构造器的 prototype 是否出现在对象原型链上,并且可被 Symbol.hasInstance 自定义。
  • 误区:Object.prototype.toString.call 永远无法伪造。 对象可通过 Symbol.toStringTag 影响标签,因此安全校验不能只依赖显示字符串。
  • 追问:为什么跨 iframe 的数组可能让 instanceof Array 失败? 不同 realm 拥有不同的 Array 构造器与 prototype,而数组原型链未必包含当前 realm 的 Array.prototype
  • 追问:typeof 未声明标识符为什么通常返回 undefined? typeof 对不可解析引用有特殊处理;但处于 temporal dead zone 的词法绑定仍可能抛 ReferenceError。
  • 追问:Number.isNaN 与全局 isNaN 有何区别? 前者不做强制类型转换,仅真正的 NaN 为真;后者先转数值,字符串等输入可能产生意外结果。
  • 追问:运行时接口数据该怎样校验? 类型探测只能验证局部类别,还应检查字段存在性、范围、联合分支和嵌套结构,必要时使用 schema 校验器。

八、加强记忆

类型题可以按“三把尺”回答:typeof 看基础类型,instanceof 看原型链,Object.prototype.toString 做精确识别。一定要主动提 typeof null 和数组判断,这是高频坑点。