typeof 与 instanceof 的区别是什么?
面试速答(30 秒版 TL;DR)
typeof:判断“值的原始类型标签”,对原始类型(除null)好用;对对象只会给"object"(函数是"function")。instanceof:判断“构造函数的prototype是否出现在对象的原型链上”,适合判断对象的具体实例(如Date),不适合判断原始类型。- 常用组合:
x === null(判 null) +Array.isArray(x)(判数组) +typeof x(判原始类型/函数) +x instanceof Xxx(判某类对象)。
心智模型:typeof 看“值”,instanceof 看“原型链”
typeof:返回的是字符串标签(对对象粒度粗)
常见返回值
typeof undefined; // "undefined"
typeof true; // "boolean"
typeof 1; // "number"
typeof 1n; // "bigint"
typeof "a"; // "string"
typeof Symbol("x"); // "symbol"
typeof function () {}; // "function"
typeof {}; // "object"
typeof []; // "object"
typeof null; // "object" (历史遗留坑)
适用场景
- 判断是否未定义:
typeof x === "undefined"(对“未声明变量”也安全) - 判断是否函数:
typeof x === "function" - 判断是否原始类型(排除
null):x !== null && typeof x !== "object" && typeof x !== "function"
常见坑
typeof null === "object"是历史 bug,判断 null 直接x === null。typeof []/typeof new Date()/typeof /re/都是"object",无法细分对象子类型。
instanceof:看原型链是否“挂上了”某个 prototype
基本用法与直觉
const d = new Date();
d instanceof Date; // true
d instanceof Object; // true (Date 的原型链最终会到 Object.prototype)
对原始类型不适用(除非显式装箱)
1 instanceof Number; // false
new Number(1) instanceof Number; // true (但不推荐用包装对象)
它到底在比什么?(面试可口述)
核心逻辑等价于:
function myInstanceof(obj, Ctor) {
if (obj == null) return false;
let p = Object.getPrototypeOf(obj);
const target = Ctor.prototype;
while (p) {
if (p === target) return true;
p = Object.getPrototypeOf(p);
}
return false;
}
你可以把它理解为:obj.__proto__ 一路往上走,看有没有遇到 Ctor.prototype。
典型题 & 标准答法
Q1:为什么 [] instanceof Array 为真,但 typeof [] 还是 "object"?
typeof对对象只给"object"(函数除外),不区分数组/日期/正则。instanceof走原型链:数组对象的原型链上有Array.prototype,所以为真。
Q2:什么时候 instanceof 会“不准”?
- 跨 realm(例如 iframe)时:不同全局对象的
Array/Date构造函数不是同一个引用,instanceof可能失败。 - 被篡改原型链时:如果对象的原型链被手动改过,也会影响结果。
- 类支持自定义:类/函数可以通过
Symbol.hasInstance改写instanceof行为(少见,但面试可以提一句“可被重载”)。
常见追问
- “那数组/日期/正则怎么检测更稳?”
- 数组:
Array.isArray(x) - 日期:
x instanceof Date(不跨 realm 时很好用) - 更通用:
Object.prototype.toString.call(x),例如"[object Date]"、"[object Array]"
- 数组:
- “为什么判断
undefined推荐用typeof?”- 因为对未声明变量
typeof notDeclared也不会抛错,结果仍是"undefined"。
- 因为对未声明变量
易错点/坑(速记)
null:只能x === null。- 数组:优先
Array.isArray(x)。 instanceof:本质是“原型链包含关系”,不是“类型标签”;跨 iframe 可能翻车。- 不要用
new Number/String/Boolean作为业务数据类型。