普通视图

发现新文章,点击刷新页面。
今天 — 2026年3月8日首页

最基础的类型检测工具——typeof, instanceof

作者 左夕
2026年3月8日 11:58

typeofinstanceof 是 JavaScript 中两个最基础但也最容易让人困惑的类型检测工具。要深入理解它们的原理,我们需要从 JavaScript 的底层数据存储、类型系统和原型链机制入手。


typeof

typeof 是一个一元运算符,它的核心任务是返回一个代表操作数类型的字符串。其原理深入到 JavaScript 引擎是如何在底层存储和标识变量的。

1. 核心原理:底层类型标签(Type Tagging)

在 JavaScript 的早期实现中,值在引擎内部是由一个**类型标签(Type Tag)**和实际的数据值来表示的。这个类型标签存储在变量的机器码低位中,用于标识该值的类型。

  • 底层存储机制:JavaScript 引擎在存储变量时,会在内存中为变量分配空间,并用低位的1-3个比特位来存储其类型信息。
  • typeof 的工作方式:当你对变量使用 typeof 操作符时,JavaScript 引擎并不会去回溯变量的创建过程,而是直接读取这个变量在内存中机器码低位的类型标签,然后将其映射为对应的类型字符串返回。

2. 机器码的类型映射

不同的类型对应着不同的低位标识。一个常见的类型标签映射如下:

  • 000:对象(object)。
  • 010:浮点数(number)。
  • 100:字符串(string)。
  • 110:布尔值(boolean)。
  • 1:整数(number),整数类型标签是1,但会被归为 number 类型。
  • -2^30undefined

3. 著名的历史遗留问题:typeof null === 'object'

这是 JavaScript 中最著名的Bug之一,至今未被修复以保持兼容性。

  • 原因:如前所述,对象的类型标签是 000。而**null 在底层表示的是空指针,在大多数实现中,空指针的机器码全是 0**。因此,当 typeof 读取 null 的类型标签时,发现是 000,就错误地将其判断为 object

4. 特例:函数的识别

虽然函数在底层也是对象(类型标签是 000),但 typeof function(){} 返回的是 'function'。这是因为 JavaScript 引擎内部对可调用对象做了特殊处理。当 typeof 操作符检测到一个对象内部实现了 [[Call]] 方法时,它会特殊处理并返回 "function"


instanceof

instanceof 是一个二元运算符,用于检测一个对象的原型链上是否存在另一个构造函数prototype 对象。它的核心是原型链查找

1. 核心原理:原型链检查

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。其内部机制可以简单地用以下代码模拟:

function myInstanceof(instanceObj, constructorFunc) {
    // 1. 获取实例对象的隐式原型(内部 [[Prototype]] 属性)
    let proto = Object.getPrototypeOf(instanceObj);

    // 2. 获取构造函数的显式原型
    let prototype = constructorFunc.prototype;

    // 3. 沿着原型链向上查找
    while (true) {
        // 4. 如果找到头(null)还没找到,返回 false
        if (proto === null) {
            return false;
        }
        // 5. 如果找到了匹配的原型,返回 true
        if (proto === prototype) {
            return true;
        }
        // 6. 继续向上一级查找
        proto = Object.getPrototypeOf(proto);
    }
}

2. 工作步骤详解

假设我们执行 obj instanceof Constructor,引擎会执行以下步骤:

  1. 获取隐式原型:获取左侧对象 obj 的内部 [[Prototype]] 属性(在浏览器中可以通过非标准 __proto__ 或标准 Object.getPrototypeOf() 访问)。
  2. 获取显式原型:获取右侧构造函数 Constructorprototype 属性。
  3. 循环比较:将 obj 的隐式原型与 Constructor 的显式原型进行比较。
    • 如果相等,返回 true
    • 如果不相等,则将 obj 的隐式原型的隐式原型(即原型链的上一级)取出来,再次与 Constructor.prototype 比较。
    • 这个过程持续进行,直到原型链的末端(即 null)。如果一直没找到相等的对象,则返回 false

3. 重要特征

  • 跨窗口问题instanceof 依赖于原型链,因此它不能跨不同的全局执行环境(例如,来自 iframe 的数组在父页面中使用 array instanceof parentWindow.Array 会返回 false),因为它们的原型链指向的是不同的 Array.prototype 对象。
  • 只能用于对象:由于 instanceof 的机制是查找原型链,对于原始类型(string, number, boolean 等),它们不是对象,没有原型链,因此直接用 instanceof 检测原始类型会始终返回 false

总结对比

特征 typeof instanceof
本质原理 读取变量机器码低位的类型标签 遍历左侧对象的原型链,查找右侧构造函数的 prototype
返回值 字符串(如 "string", "object", "function" 布尔值(true / false
适用场景 检测原始类型(除 null 外)和函数。 检测对象类型及其继承关系。
局限性 null 返回 "object";数组、日期等对象均返回 "object",无法细分。 不能跨窗口(iframe)使用;不能用于检测原始类型。
❌
❌