更新时间2013-11-05:为了更好的解释为什么typeof null的结果是object,我看了一下C代码的实现(译者注:Javascript源码)。
 
    在Javascript语言中,typeof null的结果是object。这样就会错误的认为null是一个对象(事实上,它不是一个对象,它是原始值,详细的说明可以看我的发布的博客 Javascript中的数据类型 )。很不幸,它是一个不能修复的bug,因为修复后会破坏掉现有的代码。那么。让我们探索一下这个bug的起源吧。
 
    这个bug是第一版Javascript留下来的。在这个版本,数值是以32字节存储的,由标志位(1~3个字节)和数值组成。标志位存储的是低位的数据。这里有五种标志位:
  • 000:对象,数据是对象的应用。
  • 1:整型,数据是31位带符号整数。
  • 010:双精度类型,数据是双精度数字。
  • 100:字符串,数据是字符串。
  • 110:布尔类型,数据是布尔值。
    最低位有一位,那么标志位只有一个1字节长度;或者是零位,标志位有3个字节长度,多出两个了字节,一共多出四种类型。
 
    有两个特殊的数值:
  • undefined(JSVAL_VOID)是-2^30(一个超出整数范围的数字)
  • null(JSVAL_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(VOD)。是通过比较值:
 #define JSVAL_IS_VOID(v)  ((v) == JSVAL_VOID)
//译者注:比较值是否与undefined值相等
  • 注释(2),判断值是否有对象的标志位。如果它是可调用的,或者说通过内部属性[[Class]]可以表明它是一个函数。否者它就是一个对象。这也就是typeof null的执行结果。
  • 随后是针对数字、字符串和布尔值的检测。这里并没有明确的检测null,源码中本应该有这样的实现:
 #define JSVAL_IS_NULL(v)  ((v) == JSVAL_NULL)
//译者注:本身应该存在一个类似检测undefined一样的方法,来检测null,但是事实证明它并没有
 
    这看起来像是一个很明显的bug,但是不要忘了Javascript的第一个版本花费了很少的时间完成的。
 
    感谢:感谢 Tom Schuster (@evilpies)告诉我Javascript源码 源码地址
 
 
 
 
 

【译】typeof null的前世今生的更多相关文章

  1. typeof null 为什么等于 object?

    之前只知道typeof null = object,但是却从来不知道是为什么.最新查阅资料的时候,看到了这个原理,记录下来,方便自己以后查看. 原理是这样的,不同的对象在底层都表示为二进制,在 Jav ...

  2. V8 的 typeof null 返回 "undefined" 的 bug 是怎么回事

    1997 年,IE 4.0 发布,带来的众多新特性中有一个对未来“影响深远”的 DOM API:document.all.在随后的 6 年里,IE 的市场占有率越来越高,直到 2003 年的 95%. ...

  3. JavaScript数据类型 typeof, null, 和 undefined

    JavaScript 数据类型 在 JavaScript 中有 5 种不同的数据类型: string number boolean object function 3 种对象类型: Object Da ...

  4. JavaScript typeof, null, 和 undefined

    typeof 操作符 你可以使用 typeof 操作符来检测变量的数据类型. 实例 typeof "John"                // 返回 string typeof ...

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

    我的翻译小站:https://www.zcfy.cc/article/the-history-of-typeof-null 翻译原文链接:http://2ality.com/2013/10/typeo ...

  6. null与对象的复杂关系(typeof null的结果是object的原因)

    原文 简书原文:https://www.jianshu.com/p/c1608452d056 前言 对象是 JavaScript 的基础.在 JavaScript 中一共有六种主要类型(术语是“语言类 ...

  7. 在 JavaScript 中为什么 typeof null 的结果是 object?

    java 中的 null:既是对象,又不是对象,史称「薛定谔的对象」. typeof null==='object';  ..//true null instanceof Object  //fals ...

  8. 你真的知道typeof null的结果为什么是‘object‘吗?

    到目前为止,ECMAScript 标准中定义了8种数据类型,它们分别是Undefined.Null.Number.Boolean.String.Symbol.BigInt.Object. 为了判断变量 ...

  9. 走进javascript——类型

    ECMAScript语言类型对应于使用ECMAScript语言的ECMAScript程序员直接操作的值.ECMAScript语言类型有以下几种Undefined,Null,Boolean,String ...

随机推荐

  1. wpf在异步中给前台赋值

    wpf,新建异步方法: Thread newThread = new Thread(new ParameterizedThreadStart(GetResult)); newThread.Start( ...

  2. XSHELL使用技巧总结

    1. 配置鼠标右键直接黏贴,选中直接复制(和putty行为一致) 工具->选项->键盘和鼠标,向右按钮 2. 如何在不同的选项卡切换 查看->会话选项卡

  3. 11636 - Hello World! (贪心法)

    Problem A Hello World!  Input: Standard Input Output: Standard Output When you first made the comput ...

  4. Android Fragment 详解(一)

    Android从3.0开始引入fragment,主要是为了支持更动态更灵活的界面设计,比如在平板上的应用.平板机上拥有比手机更大的屏幕空间来组合和交互界面组件们.Fragment使你在做那样的设计时, ...

  5. 字符串数组越界bug(2)

    概述 数组下标从0開始,尽管从初学都已经知道,<陷阱与缺陷>重复强调,而在指尖运动中,就有那么几次不小心,让"精子"掉进这个"洞里"!其次,C语言字 ...

  6. sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决)

    sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决) 出现此错误主要是因为.sql的脚本文件过大(一般都超过100M)造成内存无法 ...

  7. Ajax原生XHR对象

    前端学了有一段时间了,在项目中我通常使用的都是jQuery封装好的Ajax函数($.ajax.$.get.$.post),使用非常的简单方便,但为了更清楚的了解Ajax,需要学习原生xhr对象.   ...

  8. .net I/O操作 导图

    稍微总结下,System.IO提供了四种类型来实现,对单个文件和计算机目录结构的操作.Directory和File通过静态成员实现建立.删除.复制和移动操作(上图没有提及).而FileInfo和Dir ...

  9. python 下的数据结构与算法---5:递归(Recursion)

    定义:递归就是不断分割整体成部分直到可以轻易解决分割出来的部分. 递归表达式三定律: 1:递归表达式必须有个最小单元     (最小单元既是停止递归调用以及能够直接运算的) 2:递归表达式在运算过程中 ...

  10. Android开发:碎片Fragment完全解析fragment_main.xml/activity_main.xml

    Android开发:碎片Fragment完全解析   为了让界面可以在平板上更好地展示,Android在3.0版本引入了Fragment(碎片)功能,它非常类似于Activity,可以像 Activi ...