我正在阅读《Web开发专业JavaScript》第四章,书中告诉我原始类型有五种: undefined, null, boolean, number和string。
既然null
是一种原始类型,那么为什么typeof(null)
会返回"object"
?
这是否意味着null
被按引用传递(我在这里假设所有对象都是按引用传递),从而使其不是一种原始类型?
我正在阅读《Web开发专业JavaScript》第四章,书中告诉我原始类型有五种: undefined, null, boolean, number和string。
既然null
是一种原始类型,那么为什么typeof(null)
会返回"object"
?
这是否意味着null
被按引用传递(我在这里假设所有对象都是按引用传递),从而使其不是一种原始类型?
typeof null === 'null'
总是会引起比任何人都能预测到的更为深远和广泛的问题。我也讨厌 typeof null === 'object'
,但仅基于理想而争辩它不应该这样是无知的争论。 - John Millernull
和 undefined
,你可以在任何东西上调用方法。 - Matt Ball.
或[ ]
)结合使用时,字符串原始类型(以及数字和布尔原始类型)会被隐式自动地“自动装箱”为String、Number和Boolean包装器。 - Pointy正如已经指出的那样,规范是这么说的。但由于JavaScript的实现先于ECMAScript规范的编写,并且规范小心翼翼地不纠正初始实现的怪异行为,因此仍然存在一个合理的问题,即首先为什么要这样做。Douglas Crockford 称其为错误。Kiro Risk 认为这有点道理:
其背后的原因是,与
undefined
不同,null
经常被用在对象出现的地方。换句话说,null通常用来表示对对象的空引用。当Brendan Eich创建JavaScript时,他遵循了相同的范例,返回"object"也讲得通(可以说)。事实上,ECMAScript规范将null
定义为表示任何对象值的有意缺席的原始值(ECMA-262,11.4.11)。
来自书籍 YDKJS
这是JS中长期存在的一个bug,但很可能永远不会被修复。因为太多Web上的代码依赖这个bug,修复它会导致更多的bug!
typeof null
是 object
只是意味着规范选择将该 bug 作为规范的一部分。无论如何,这就是为什么我认为它是一个 bug 的原因。 :) - BobRodesnull
// 这是 JavaScript 从一开始就存在的
typeof null === 'object';
简短回答:
这是自 ECMAScript 发布以来的一个错误,但不幸的是无法修复,因为这会破坏现有的代码。
解释:
然而,在 JavaScript 中将 null 定义为对象实际上是有一个逻辑解释的。
在 JavaScript 的初始版本中,值存储在32位单元中,其中包括一个小的类型标记(1-3位)和值的实际数据。类型标记存储在单元的低位中。共有五种类型标记:
000: object. The data is a reference to an object.
1: int. The data is a 31 bit signed integer.
010: double. The data is a reference to a double floating point number.
100: string. The data is a reference to a string.
110: boolean. The data is a boolean.
typeof null === 'null'。
++作者的回答是:
我认为修复 typeof 已经太晚了。对于 typeof null 提出的更改将会破坏现有代码。
时间已经晚了。自从微软创建了自己的 JavaScript 引擎并复制了第一个引擎版本的所有功能和缺陷以来,所有后续的引擎都复制了这个错误,现在修复它已经太晚了。
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;
}
由于历史原因,6.1.1 未定义类型
6.1.2 空类型
6.1.3 布尔类型
6.1.4 字符串类型
6.1.5 符号类型
6.1.6 数值类型
6.1.6.1 数字类型
6.1.6.2 大整数类型
6.1.7 对象类型
typeof
运算符在两种情况下与此分类不一致:
typeof null == "object"
:这是不幸的,但我们必须接受。typeof
计算结果为"function",尽管根据规范它的数据类型为对象。instanceof
-- 可以用来判断一个对象是否从某个原型继承而来。例如,[1,2] instanceof Array
将会返回 true。Object
函数:if (Object(value) === value) // then it is an object; i.e., a non-primitive
这是来自 JavaScript 第一个版本的一个 bug 残留。
“这是一个 bug,不幸的是它无法修复,因为这会破坏现有的代码。”
typeof
是一个操作符而不是一个函数,因此你的代码中的括号是不必要的 - 你可以直接使用语法typeof null
。 - Oliver Sieweke(typeof +(\w+) +={2,3} +"object")
到($2 && $1)
,以便在可能存在的任何地方修复此问题。这将把typeof arg === "object"
转换为(arg && typeof arg === "object")
。 - Seph Reed