【译】谈谈“typeof null为object”这一bug的由来

栏目: C · 发布时间: 5年前

内容简介:很多前端初级开发者也许并不深究typeof null为何为Object?想更深地了解这一bug的由来,可以参阅Dr. Axel Rauschmayer关于"typeof null"的历史这篇文章。原文链接:我看了下C语言关于

很多前端初级开发者也许并不深究typeof null为何为Object?想更深地了解这一bug的由来,可以参阅Dr. Axel Rauschmayer关于"typeof null"的历史这篇文章。

原文链接: www.2ality.com/2013/10/typ…

我看了下 C语言 关于 typeof 的规范,它对于 typeof null 为何结果是’ object ’有更好的解释。

在JavaScript中, typeof null 的结果是' Object ',它错误地暗示 null 是一个对象,实际上它是一个原始值。我在上一篇文章也提到了这是JS的一大bug,不幸的是这并不能解决,因为这将破坏现有规范,接下来解释下这个bug的历史。

typeof null ”的错误从JavaScripts第一个版本开始就已经存在了。在这个版本,值以32位为单位存储,由小型标签(1-3位)和值的实际数据组成。类型标签存储在单元的低位中。 其中有五种:

object
int
double
string
boolean

也就是说,最低位是1,然后类型标签只有1位长,即 int 型。 或者最低位为0,那么类型标签的长度为3位,为其余4种类型提供了两个附加位。

但有2个值是特殊的:

undefined
null

现在应该明白为什么 typeof 认为 null 是一个对象:它检测一个他的类型标签并且返回” object ”。 以下是 typeof 的引擎代码:

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)引擎首先检测值是否是 undefined (VOID),它通过 == 做了这样的比较:
#define JSVAL_IS_VOID(v)  ((v) == JSVAL_VOID)
复制代码
  • 下一个(2)是检测该值是否具有 object type 。如果它可使用 call 被调用(3)或其存在内部属性 [[Class]] 标记为函数(4),则v是函数。 否则,它是一个对象。 这是由 typeof null 生成的结果。

  • 后续检查是针对 numberstringboolean ,甚至没有明确检查 null 。这可以由以下C语言宏执行。

#define JSVAL_IS_NULL(v)  ((v) == JSVAL_NULL)`  
复制代码

这看似是一个非常明显的bug,但不要忘记,第一个版本的JavaScript完成只用了极少的时间,具体可以看看JavaScript的诞生。

如果觉得文章对你有些许帮助,欢迎在 我的GitHub博客 点赞和关注,感激不尽!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Bad Blood

Bad Blood

John Carreyrou / Knopf / 2018-5-21 / USD 27.95

The full inside story of the breathtaking rise and shocking collapse of Theranos, the multibillion-dollar biotech startup, by the prize-winning journalist who first broke the story and pursued it to t......一起来看看 《Bad Blood》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具