类型检测需按问题选择工具:问原始值用typeof,问构造器用instanceof;typeof快但无法区分对象类型,instanceof可判实例但跨环境失效;实际应优先用Array.isArray()或Object.prototype.toString.call()。
JavaScript 类型检测不是选一个“对的”运算符就完事,而是根据你要回答的问题来选:是问“它是什么原始值?”,还是问“它是不是某个类造出来的?”。typeof 和 instanceof 根本不是同一类工具,硬比谁“更好”容易踩坑。
typeof:判断基本类型或变量是否存在typeof 本质是读取 JS 引擎给值打的“类型标签”,所以快、轻量、安全(不会报错),但只认原始类型和 function;对所有对象(包括数组、日期、正则、null)一律返回 "object" —— 这不是 bug,是设计如此。
if (typeof cb === "function") { cb() }、检查变量是否声明:typeof window !== "undefined"
ty
peof null 返回 "object",typeof [] 和 typeof {} 都是 "object",无法区分Date、Array、RegExp 等具体构造器类型instanceof:确认对象由哪个构造函数创建instanceof 不看类型标签,而是顺着对象的 __proto__ 链往上找,看能不能碰到右操作数的 .prototype。它回答的是“这个对象是不是 new X() 出来的?”而不是“它是什么类型?”
arr instanceof Array(在单窗口下可靠)、date instanceof Date
iframe.contentWindow.Array 和主页面的 Array 是两个构造器)"abc" instanceof String 永远是 false(字符串字面量不是 String 实例)单独用 typeof 或 instanceof 都会漏判。实际项目中常组合使用,或换更稳的方案:
Array.isArray()(ES5+,跨 frame 安全),比 arr instanceof Array 更可靠Object.prototype.toString.call(value),例如:Object.prototype.toString.call(new Date()) // "[object Date]"
function getType(obj) { return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); }
最易被忽略的一点:类型检测从来不是为了“分类而分类”,而是服务于后续逻辑分支。别在 if 条件里堆砌 typeof x === "object" && x !== null && x.constructor === Array 这种脆弱判断——直接用 Array.isArray(x) 或 value instanceof Map(明确知道运行环境)更干净。类型检测的终点,是让代码不崩溃、不误判、不依赖隐式转换。