When the whole world is about to rain, let's make it clear in our heart together

热爱前端开发,专注于前端

【翻译】追溯“typeof null”的历史

我的翻译小站:https://www.zcfy.cc/article/the-history-of-typeof-null

翻译原文链接:http://2ality.com/2013/10/typeof-null.html  

 

更新2013-11-05:我发现用C语言能够很好的解释为什么typeof null 结果是'object'。

在JavaScript中,typeof null 是 'object',它错误地将null认为是对象(其实它不是,它是一个原始的值,详情可查询 categorizing values )。这是一个bug,不幸地是无法被修复,因为它会破坏现有的代码。让我们一起来探索一下这个bug的历史吧。

从JavaScript第一个版本,“typeof null” 就是一个bug坑。这个版本里,值被以32位单位保存, 包括小类型标签(1-3位)和实际数据的值。这种类型标签被以更低的单位保存。这里有其中的五个:

  • 000: 对象。数据是对对象的引用。

  • 1: 整型。数据是31位带符号整数。

  • 010: 浮点型。数据是对浮点数据的引用。

  • 100: 字符。 数据是对字符串类型的引用。

  • 110: boolean. 数据是boolean。

也就是说,最低位是任意一个,那么类型标签是只有1位长。或者是0,那么类型标签的长度为3位,就会为4种类型提供了额外的2位。

有2种值是特殊的:

  • undefined (JSVAL_VOID)是整数−(2^30)(数值在整数范围外)。

  • null (JSVAL_NULL) 是代码空指针。或者:一个对象类型标签加上一个为零的引用。

现在很明显,为什么 typeof null 被认为是对象:它检查了它的类型标签,类型标签说是“object”。下面是 typeof的引擎代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  JS_PUBLIC_API(JSType)
    JS_TypeOfValue(JSContext *cx, jsval v)
    {
        JSType type = JSTYPE_VOID;
JSObject *obj;
JSObjectOps *ops;
JSClass *clasp;
CHECK_REQUEST(cx);
if (JSVAL_IS_VOID(v)) {  // (1)
            type = JSTYPE_VOID;
} else if (JSVAL_IS_OBJECT(v)) {  // (2)
            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) // (3,4)
                 : ops->call != 0)) {  // (3)
                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;
}

执行步骤如上代码所示:

  • 在(1)中,引擎首先检查值v 是否是undefined (VOID)。比较两个值是否相等。

    1
    <em id="__mceDel">#define JSVAL_IS_VOID(v)  ((v) == JSVAL_VOID)<br></em>
  • 接下来(2)是检查值是否有对象标签。如果它是可调用的(3)或者它的内部属性[[Class][]将它标记为一个函数(4)那么' v '就是一个函数。否则,它就是一个对象。这是' typeof null '生成的结果。

  • 接下来是检查数字,字符串和boolean。这里没有给null明确的检查,它可以由C宏观执行。

    1
    #define JSVAL_IS_NULL(v)  ((v) == JSVAL_NULL)

这看起来像是很显而易见的bug,但是不要忘记,完成第一个JavaScript版本的时间很少。

致敬: 感谢Tom Schuster (@evilpies指出JavaScript原始代码.

 


作者:婷风

 出处:https://www.cnblogs.com/jtjds/p/10413480.html  

 如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意 

转载文章之后必须在 文章页面明显位置给出作者和原文连接否则保留追究法律责任的权利。

posted @   婷风  阅读(469)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示