【譯】typeof null的前世今生


    更新時間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源碼 源碼地址
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM