一、typeof 基本用法与返回值
1. 语法与核心功能
typeof 是 JavaScript 的一元操作符,用于返回一个表示数据类型的字符串。其语法为:
typeof operand
typeof(operand) // 括号可选,但不影响结果
示例:
typeof 42; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof Symbol(); // "symbol"
typeof null; // 注意:"object"(历史遗留问题)
2. 基本数据类型检测
值类型typeof 返回值数值(Number)“number”字符串(String)“string”布尔值(Boolean)“boolean”未定义(Undefined)“undefined”符号(Symbol)“symbol”空值(Null)“object”(错误!)特殊案例分析:
// 数值类型
typeof 123; // "number"
typeof NaN; // "number"(NaN 属于数值类型)
typeof Infinity; // "number"
// 字符串类型
typeof ""; // "string"
typeof String(123); // "string"(显式类型转换)
// 布尔类型
typeof false; // "boolean"
typeof Boolean(0); // "boolean"
// Undefined
typeof undeclaredVariable; // "undefined"
typeof void 0; // "undefined"(void 操作符强制返回 undefined)
// Symbol
typeof Symbol('foo'); // "symbol"
typeof Symbol.iterator; // "symbol"
二、typeof 对引用类型的处理
1. 对象(Object)
typeof {}; // "object"
typeof []; // "object"
typeof new Date(); // "object"
typeof /regex/; // "object"
typeof null; // "object"(历史错误,无法修复)
2. 函数(Function)
typeof function() {}; // "function"
typeof Math.sin; // "function"
typeof class {}; // "function"(类本质是函数)
typeof async () => {}; // "function"(异步函数)
typeof function*() {}; // "function"(生成器函数)
3. 特殊对象类型
// 所有内置对象(除 Function 外)均返回 "object"
typeof new Error(); // "object"
typeof new Map(); // "object"
typeof new Set(); // "object"
typeof new WeakMap(); // "object"
typeof new WeakSet(); // "object"
typeof new ArrayBuffer(); // "object"
三、typeof 的局限性与陷阱
1. null 的错误返回
typeof null === "object"; // true(JavaScript 历史上的最大错误之一)
原因:JavaScript 早期版本使用低位标记类型信息,null 的标记为全0,与对象的标记格式冲突。
替代检测方案:
const isNull = (value) => value === null;
// 或使用严格相等判断
console.log(null === null); // true
2. 无法区分不同对象类型
typeof [] === typeof {}; // true(均返回 "object")
typeof new Date() === typeof /regex/; // true
替代检测方案:
使用 Array.isArray() 检测数组:Array.isArray([]); // true
Array.isArray({}); // false
使用 instanceof 检测对象类型:[] instanceof Array; // true
new Date() instanceof Date; // true
/regex/ instanceof RegExp; // true
使用 Object.prototype.toString.call():Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(null); // "[object Null]"
3. 对未声明变量的安全处理
// 安全访问未声明变量
typeof undeclaredVariable; // "undefined"(不会抛出 ReferenceError)
// 对比直接访问
undeclaredVariable; // 抛出 ReferenceError
应用场景:条件加载模块时避免错误:
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
// 模块环境
} else {
// 浏览器环境
}
四、typeof 与变量声明的关系
1. 未声明 vs 已声明但未赋值
// 未声明变量
typeof x; // "undefined"
// 已声明但未赋值
let y;
typeof y; // "undefined"
2. 块级作用域与 TDZ(暂时性死区)
console.log(typeof z); // ReferenceError(TDZ 内访问)
let z = 10;
五、typeof 在条件判断中的应用
1. 基本类型保护
function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new TypeError('Both arguments must be numbers');
}
return a + b;
}
2. 函数参数类型检查
function processData(callback) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function');
}
// 执行回调
callback();
}
3. 可选依赖检查
if (typeof SomeLibrary !== 'undefined') {
// 使用 SomeLibrary
} else {
// 备选逻辑
}
六、typeof 与其他类型检测方法的对比
1. typeof vs instanceof
特性typeofinstanceof返回值类型字符串布尔值能检测基本类型是(除 null 外)否(仅适用于对象)能检测具体对象类型否(仅区分 function)是(需明确构造函数)跨窗口/iframe 支持是否(不同 window 的 Array 不共享原型)2. typeof vs Object.prototype.toString.call()
// 对比示例
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
优势:能精确区分所有内置对象类型。
封装工具函数:
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(getType([])); // "Array"
console.log(getType(new Map())); // "Map"
console.log(getType(null)); // "Null"
七、typeof 在现代 JavaScript 中的应用
1. ES6 模块检测
if (typeof importScripts === 'function') {
// Web Worker 环境
importScripts('worker.js');
}
2. 异步函数检测
function isAsyncFunction(fn) {
return typeof fn === 'function' && fn.constructor.name === 'AsyncFunction';
}
3. 符号类型保护
const sym = Symbol();
if (typeof sym === 'symbol') {
// 使用符号
}
八、常见面试题与陷阱
1. 为什么 typeof null 是 “object”?
答案:JavaScript 早期版本使用低位标记类型信息,null 的标记为全0,与对象的标记格式冲突,导致误判。
2. 如何可靠地检测数组类型?
答案:Array.isArray([]); // 首选方法
// 或
Object.prototype.toString.call([]) === '[object Array]';
3. 以下代码的输出是什么?
typeof typeof 1;
答案:"string"
解析:typeof 1 返回 "number",再对 "number" 使用 typeof 返回 "string"。
九、总结:typeof 的正确使用姿势
适合场景:
快速区分基本数据类型(除 null 外)检测变量是否已声明(避免 ReferenceError)函数参数类型的基本校验
不适合场景:
精确判断对象类型(如数组、日期等)检测 null 值跨窗口/iframe 的对象类型检测
推荐组合策略:
使用 typeof 检测基本类型使用 Array.isArray() 检测数组使用 instanceof 检测自定义对象类型使用 Object.prototype.toString.call() 进行精确类型检测
掌握 typeof 的特性与局限性,结合其他类型检测方法,能帮助开发者写出更健壮、更具容错性的 JavaScript 代码。