zoukankan      html  css  js  c++  java
  • 【译】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源码 源码地址
     
     
     
     
     
  • 相关阅读:
    springboot springdata 整合es
    forkJoinPool
    springboot整合ElasticSearch
    雪花算法生成全局唯一ID
    linux环境下elasticsearch+kibana+ik(实现热词自动更新)
    ECMAScript 6新特性简记
    Tsung:开源多协议分布式负载&压力测试工具
    js 数组迭代方法总结
    js for循环
    箭头函数this的问题
  • 原文地址:https://www.cnblogs.com/xiaoheimiaoer/p/4572558.html
Copyright © 2011-2022 走看看