typeof null === 'object'的原因

2021-08-12  本文已影响0人  AAA前端

typeof

操作符唯一的目的就是检查数据类型

类型 typeof结果
undefined 基本类型 'undefined'
Boolean 基本类型 'boolean'
Number 基本类型 'number'
String 基本类型 'string'
BigInt (ECMAScript 2020 新增) 基本类型 'bigint'
Symbol 基本类型 'symbol'
null 基本类型 'object'
Object(Object、Array、Map、Set等) 引用类型 'object'
Function 引用类型 'function'

在 JavaScript 中,typeof null是'object',它错误地表明null是一个对象(它不是,它是一个原始值)

“typeof null”错误是 JavaScript 第一个版本的残余。在这个版本中,值以 32 位为单位存储,它由一个小型标签(1-3 位)和值的实际数据组成。类型标签存储在单元的低位中。其中有五个:

也就是说,最低位是任一位,那么类型标签只有一位长。或者它是零,那么类型标签的长度是三位,为四种类型提供两个额外的位。

两个值很特别:

现在应该很明显为什么typeof认为null是一个对象:它检查了它的类型标签,并且类型标签表示“对象”。以下是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;  // undefined
        } 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; // function
            } else {
                type = JSTYPE_OBJECT; //object
            }
        } else if (JSVAL_IS_NUMBER(v)) {
            type = JSTYPE_NUMBER; //number
        } else if (JSVAL_IS_STRING(v)) {
            type = JSTYPE_STRING; //string
        } else if (JSVAL_IS_BOOLEAN(v)) {
            type = JSTYPE_BOOLEAN; //boolean
        }
        return type;
    }

上述代码执行的步骤是:

这似乎是一个非常明显的错误,但不要忘记完成 JavaScript 的第一个版本的时间很少。

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。(参考来源

曾有一个 ECMAScript 的修复提案(通过选择性加入的方式),但被拒绝了。该提案会导致 typeof null === 'null'

Object.prototype.toString(扩展)

还有一个不错的判断类型的方法,就是 Object.prototype.toString ,我们可以利用这个方法来对一个变量的类型来进行比较准确的判断

Object.prototype.toString.call("abc"); // "[object String]"
Object.prototype.toString.call(100); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call([1,2,3]); // "[object Array]"
Object.prototype.toString.call(/\w/); // "[object RegExp]"

参考:https://2ality.com/2013/10/typeof-null.html
https://www.pzijun.cn/blog/1/1.1.html#typeof

上一篇 下一篇

猜你喜欢

热点阅读