到目前为止,ECMAScript 标准中定义了8种数据类型,它们分别是Undefined、Null、Number、Boolean、String、Symbol、BigInt、Object。为了判断变量的数据类型,JavaScript还提供了typeof操作符。但typeof操作符错误的将一个原始类型值null判断为object

到目前为止,ECMAScript 标准中定义了8种数据类型,它们分别是Undefined、Null、Number、Boolean、String、Symbol、BigInt、Object。
为了判断变量的数据类型,JavaScript还提供了typeof操作符。
数据类型中的值通过typeof操作符操作过后输出的值对应表格:

数据类型结果
Undefinedundefined'undefined'
Nullnull'object'
Number1、1.0、NaN、Infinity'number'
Booleantrue、false'boolean'
String'' 、'abc''string'
SymbolSymbol()、Symbol('123')'symbol'
BigInt0n、1n'bigint'
Object{}、[]'object'
Objectfunction(){}'function'

通过观察,我们可以发现一个问题——typeof操作符错误的将一个原始类型值null判断为object

typeof null === 'object'//true

这将导致typeof x === 'object'时,x还有可能是null

这个问题的产生可以追溯到JavaScript的第一个版本[1],在这个版本中,单个值在栈中占用32位的存储单元,而这32位的存储单元又可以划分为类型标签(1-3位)和实际数据,类型标签存储于低位中,具体可以分成5种:

(1)

如图[2],当第0位、第1位和第2位皆为0时,typeof判断类型为'object';

(2)

如图[2:1],当第0位为1时,typeof判断类型为'number(整数)';

(3)

如图[2:2],当第0位与第2位皆为0,而第1位为1时,typeof判断类型为'number(浮点数)';

(4)

如图[2:3],当第0位与第1位皆为0,而第2位为1时,typeof判断类型为'string';

(5)

如图[2:4],当第1位与第2位皆为1,而第0位为0时,typeof判断类型为'boolean';

此外还有两种特殊情况:
undefined:整数−2^30 (整数范围之外的数字)
null:第0位到第31位皆为0(正好满足当第0位、第1位和第2位皆为0时,typeof判断类型为'object'的条件)

下面的代码更好的说明了这个问题(来源):

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)) {            type = JSTYPE_VOID;        } else if (JSVAL_IS_OBJECT(v)) {            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)                  : ops->call != 0)) {                 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;    }

正因如此,导致typeof null === 'object'为true。


  1. 此时还没有 Symbol、BigInt,故不在讨论范围内; ↩︎

  2. 图片来自window10计算器程序员模式; ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

©著作权归作者所有:来自51CTO博客作者wx60877cc7b61d6的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. JavaScript中判断对象是否属于Array类型的4种方法及其背后的原理
  2. 深入了解typeof与instanceof的使用场景及注意事项
  3. JavaScript中的基本字符串与字符串对象的区别
  4. msqly
  5. 两集合比较判断
  6. 关于Go语言,你可能会讨厌的五件事
  7. MySQL字符类型datetime与timestamp
  8. mysql中生成列与JSON类型的索引
  9. mysql的数据类型和字符集

随机推荐

  1. 如何执行浏览器内对比扩展/规范化?
  2. JS数据类型(一)
  3. javascript高阶函数map和reduce
  4. 粗见之正则表达式
  5. 如何在Javascript中从Json数组创建路径路
  6. jQuery插件:如何将元素引用传递给回调函数
  7. 动态的JQUERY追加父子div。
  8. 在textarea上应用0高度div的类
  9. 我可以在JavaScript中从不同的页面传递参
  10. 为什么我不能删除数组的元素?