个人翻译小站:https://www.zcfy.cc/article/the-history-of-typeof-nulljavascript
翻译原文连接:http://2ality.com/2013/10/typeof-null.html html
更新2013-11-05:我发现用C语言可以很好的解释为何typeof null 结果是'object'。java
在JavaScript中,typeof null 是 'object',它错误地将null认为是对象(其实它不是,它是一个原始的值,详情可查询 categorizing values )。这是一个bug,不幸地是没法被修复,由于它会破坏现有的代码。让咱们一块儿来探索一下这个bug的历史吧。api
从JavaScript第一个版本,“typeof null” 就是一个bug坑。这个版本里,值被以32位单位保存, 包括小类型标签(1-3位)和实际数据的值。这种类型标签被以更低的单位保存。这里有其中的五个:函数
000: 对象。数据是对对象的引用。翻译
1: 整型。数据是31位带符号整数。指针
010: 浮点型。数据是对浮点数据的引用。code
100: 字符。 数据是对字符串类型的引用。htm
110: boolean. 数据是boolean。对象
也就是说,最低位是任意一个,那么类型标签是只有1位长。或者是0,那么类型标签的长度为3位,就会为4种类型提供了额外的2位。
有2种值是特殊的:
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)中,引擎首先检查值v
是不是undefined
(VOID)。比较两个值是否相等。
#define JSVAL_IS_VOID(v) ((v) == JSVAL_VOID)
接下来(2)是检查值是否有对象标签。若是它是可调用的(3)或者它的内部属性[[Class][]将它标记为一个函数(4)那么' v '就是一个函数。不然,它就是一个对象。这是' typeof null '生成的结果。
接下来是检查数字,字符串和boolean。这里没有给null
明确的检查,它能够由C宏观执行。
#define JSVAL_IS_NULL(v) ((v) == JSVAL_NULL)
这看起来像是很显而易见的bug,可是不要忘记,完成第一个JavaScript版本的时间不多。
致敬: 感谢Tom Schuster (@evilpies) 指出JavaScript原始代码.
做者:婷风
出处:http://www.javashuo.com/article/p-myllvoyt-cb.html
若是您以为阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写做动力!欢迎各位转载,可是未经做者本人赞成
转载文章以后必须在 文章页面明显位置给出做者和原文链接不然保留追究法律责任的权利。