花费28800秒,我终于知道了 typeof null 为 object 的原理

1.背景

我之前一直知道 typeof null 为 object ,但是一直没深究为什么?在查阅了相关的文档,汇总为以下文档

2.汇总解释

我们先来看 《JavaScript高级程序设计》 里面是怎么说的吧?

Null 类型同样只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针,这也是给 typeof 传一个 null 会返回 "object" 的原因

这里我们就可以解释通了,null 其实是一个 空对象指针 ,所以 typeof 会检测 null 为 object

如果单纯是这样必然是不对的,是 空对象指针 就一定会被检测为 object 吗?

这其实就是一句总结,里面肯定有更加深层的原因,我看了一眼 ECMAScript 的文档,发现没有说这一点(可能是我没找到),倒是在 MDN 发现了解释

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"

我来简单解释一遍,对象类型 表示为 0 ,null 在大部分机器上面都是 0x00...000 ,所以 null 为 0 ,所以 null 在 typeof 下 会被检测为 object

3.详细解释

这个解释已经能解答很多疑惑了,如果我们再往下面看一层呢?为什么对象类型为 0 ,null 为 0x00 ,typeof 底层分析类型是通过什么手段?以及这部分源码是什么样子的?

其实 JavaScript 的数据类型其实是通过 数据标签 + 数据值 的形式存在的,下面就是常见的数据标签

数据标签 类型
000 object
1 int
010 double
100 string
110 boolean

在32位机器中,int 的 标签为 1 ,占了一位,那么后续的值为 2 ^ 30 ~2 ^ 30 - 1 (根据上图推算,现代JS早就改);其中 object 的标签为 000

这就是 JavaScript 的数据类型如何去做处理和区分的,当然还有2个特殊的值

  • undefined 源码标记为 JSVAL_VOID
  • null 源码标记为 JSVAL_NULL :是机器代码的 NULL****指针 。或者说,它是一个对象类型标记加上一个引用为零的组合,大部分机器都认定为 0x000

我们来看下面的 typeof 源码部分

  • 发现没有 显式的判断 null****值 的标记,只有 undefined,object,number,string,boolean 的判断
  • 再加上 null 在很多的机器中默认是 0x000 ,那么就会走 JSVAl_IS_OBJECT(v) 的逻辑,被认定为 object 类型
c 复制代码
// 这是一个宏,它指定了函数的返回类型为 JSType,并且声明该函数是一个公共API  
JS_PUBLIC_API(JSType)  
JS_TypeOfValue(JSContext *cx, jsval v) {  
    JSType type = JSTYPE_VOID;  
    JSObject *obj;  
    JSObjectOps *ops;  
    JSClass *clasp;  
     
    // 这是一个宏,用于检查传入的 JSContext 是否有效  
    CHECK_REQUEST(cx);  
     
    if (JSVAL_IS_VOID(v)) {  
        type = JSTYPE_VOID;  
    } else if (JSVAL_IS_OBJECT(v)) {  
        // 如果 v 是对象类型,则检查它是否是函数对象,如果是函数对象则将 type 设置为 JSTYPE_FUNCTION  
        // 否则将其设置为 JSTYPE_OBJECT  
        obj = JSVAL_TO_OBJECT(v);  
        if (obj && (ops = obj->map->ops, ops == &js_ObjectOps ? (clasp = OBJ_GET_CLASS(cx, obj), clasp->call || clasp == &js_FunctionClass) : ops->call != 0)) {   
            type = JSTYPE_FUNCTION;  
        } else {  
            type = JSTYPE_OBJECT;  
        }  
    } else if (JSVAL_IS_NUMBER(v)) {  
        type = JSTYPE_NUMBER;  
    } else if (JSVAL_IS_STRING(v)) {  
        type = JSTYPE_STRING;  
    } else if (JSVAL_IS_BOOLEAN(v)) {  
        type = JSTYPE_BOOLEAN;  
    }  
    return type;  
}

在 V8 Blog 对于 typeof null 为 object 的解释。我来简单解释一下:V8 Blog 认为 null 表示 no object value,所以输出 object 没问题

当然这有一股王婆卖瓜,自卖自夸的感觉了,毕竟是 JavaScript 最初设计的问题

4.总结

到这里继续深究下去已经没必要了,就是最初设计的缺陷导致的,当然这次的查询告诉我们对于高级语言的设计并不一定都是对的,如果想深究,也能看到 JavaScript 很多不合理的地方

参考文章

javascript - Why is typeof null "object"? - Stack Overflow

The story of a V8 performance cliff in React · V8

typeof - JavaScript | MDN (mozilla.org)

The history of "typeof null" (2ality.com)

typeof 与 Javascript 类型源码分析 - 知乎 (zhihu.com)

相关推荐
只睡四小时几秒前
Local-First 数据契约:一张表装下 4 类数据
前端·javascript·架构设计·local-first·数据契约
迅猛龙办公室1 分钟前
Python函数实现反转一个只有3位数的整数
开发语言·前端·python
我星期八休息1 分钟前
Redis 的原理和使用(2)
前端·数据库·redis·python·mysql·缓存·bootstrap
Java后端的Ai之路2 分钟前
19-ReactJS最佳实践
前端·react.js·前端框架
溪语流沙18 分钟前
【Web全栈进阶】文件上传与图片展示:早报站的第一张图片
前端·vue.js·python·fastapi
alwaysrun21 分钟前
Web之wasm-bindgen详解
前端·wasm·bindgen
鬼手点金31 分钟前
如何选择模型
java·前端·人工智能·git·深度学习
恋猫de小郭32 分钟前
Dart 3.15 新特性:this 终于支持类型提升了
android·前端·flutter
IT_陈寒1 小时前
Vue开发实战:从入门到精通
前端·人工智能·后端
znnnk1 小时前
2026 前端工程化新纪元:Rust 重塑工具链,AI Agent 接管流水线
前端·人工智能·rust