目录
一、基础检测方法
二、方法深度解析
1. typeof 运算符
2. instanceof 运算符
3. 终极检测方案
三、特殊场景检测方案
四、手写实现原理
1. 通用类型检测函数
2. 改进版数组检测(兼容旧浏览器)
五、常见面试陷阱
六、最佳实践指南
七、扩展知识
总结
一、基础检测方法
方法 | 能力范围 | 经典案例 | 注意事项 |
---|---|---|---|
typeof | 检测基本数据类型(除 null ) | typeof 'str' → 'string' | typeof null → 'object' (历史遗留问题) |
instanceof | 检测对象原型链 | [] instanceof Array → true | 跨窗口对象检测失效(如iframe) |
Object.prototype.toString.call() | 精确检测所有类型 | toString.call([]) → '[object Array]' | 需配合 call 改变 this 指向 |
二、方法深度解析
1. typeof 运算符
-
返回值类型:返回类型字符串
typeof 42; // "number" typeof 'text'; // "string" typeof true; // "boolean" typeof undefined; // "undefined" typeof Symbol(); // "symbol" typeof 10n; // "bigint" (ES2020+) typeof function(){};// "function" typeof {}; // "object" typeof []; // "object" (缺陷) typeof null; // "object" (著名陷阱)
2. instanceof 运算符
-
原型链检测机制:
function Car() {} const myCar = new Car(); myCar instanceof Car; // true myCar instanceof Object; // true(原型链追溯)
-
跨窗口问题:
// 不同iframe中的Array构造函数不共享原型链 iframe.contentWindow.Array !== window.Array; iframeArray instanceof Array; // false
3. 终极检测方案
const typeCheck = obj => {return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
};typeCheck([]); // 'array'
typeCheck(new Date); // 'date'
typeCheck(null); // 'null'
typeCheck(/regex/); // 'regexp'
typeCheck(Symbol()); // 'symbol'
三、特殊场景检测方案
检测需求 | 实现方案 | 示例 |
---|---|---|
数组检测 | Array.isArray() (ES5+) | Array.isArray([1,2]) → true |
NaN检测 | Number.isNaN() (ES6+) | Number.isNaN(NaN) → true |
纯对象检测 | 组合检测 | obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype |
Promise检测 | obj instanceof Promise | p instanceof Promise |
Buffer检测 | Buffer.isBuffer() (Node.js) | Buffer.isBuffer(buffer) |
四、手写实现原理
1. 通用类型检测函数
function getType(obj) {// 处理 null 的特殊情况if (obj === null) return 'null';// 处理基础类型(除 symbol)const type = typeof obj;if (type !== 'object') return type;// 处理引用类型const typeStr = Object.prototype.toString.call(obj);return typeStr.slice(8, -1).toLowerCase();
}
2. 改进版数组检测(兼容旧浏览器)
const isArray = (function() {if (typeof Array.isArray === 'function') {return Array.isArray;}return function(obj) {return Object.prototype.toString.call(obj) === '[object Array]';};
})();
五、常见面试陷阱
-
typeof
的边界情况typeof NaN; // "number"(需用 Number.isNaN 判断) typeof document.all; // "undefined" (历史遗留特性)
-
包装对象检测
const str = new String('test'); typeof str; // "object" str instanceof String; // true
-
修改对象
[[Class]]
属性const obj = {}; Object.prototype.toString.call(obj); // [object Object] obj[Symbol.toStringTag] = 'Custom'; Object.prototype.toString.call(obj); // [object Custom]
六、最佳实践指南
-
基础类型检测:优先使用
typeof
-
数组检测:统一使用
Array.isArray()
-
精确类型判断:使用
Object.prototype.toString.call()
-
构造函数检测:慎用
instanceof
(注意原型链污染风险) -
特殊值检测:
-
null
→obj === null
-
undefined
→obj === void 0
-
NaN
→Number.isNaN()
-
七、扩展知识
-
ES6 新增类型检测:
const set = new Set(); Object.prototype.toString.call(set); // [object Set]const map = new Map(); Object.prototype.toString.call(map); // [object Map]
-
BigInt 检测:
typeof 10n; // "bigint"
-
异步函数检测:
async function fn() {} Object.prototype.toString.call(fn); // [object AsyncFunction]
总结
掌握数据类型检测是JavaScript开发的基本功,针对不同场景选择合适的检测方案:
-
快速判断基本类型 → typeof
-
原型链关系验证 → instanceof
-
精确类型识别 → Object.prototype.toString.call()
-
特定类型优化 → 专用方法(如 Array.isArray)
理解这些方法的实现原理和边界条件,能够帮助开发者写出更健壮的代码,在面试中也能从容应对相关问题的深度追问。