個人翻譯小站: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
若是您以爲閱讀本文對您有幫助,請點一下「推薦」按鈕,您的「推薦」將是我最大的寫做動力!歡迎各位轉載,可是未經做者本人贊成
轉載文章以後必須在 文章頁面明顯位置給出做者和原文鏈接不然保留追究法律責任的權利。