为什么是文档.除typeof文档外所有已定义.所有返回“未定义”

Why is document.all defined but typeof document.all returns "undefined"?

本文关键字:未定义 文档 返回 定义 typeof 为什么      更新时间:2023-09-26

我正在做一些关于JavaScript的typeof运算符的研究,并偶然发现以下奇怪的:

<标题> 异常

当前所有浏览器都公开一个类型为Undefined的非标准主机对象document.all

typeof document.all === 'undefined';

尽管规范允许为非标准的外来对象定制类型标记,但它要求这些类型标记与预定义的类型标记不同。document.all具有类型标签'undefined'的情况必须归类为例外违反规则。

(源)

我在浏览器中设置了以下内容来测试它:

console.log("typeof: " + typeof document.all);
console.log("toString: " + document.all);

:

typeof: undefined
toString: [object HTMLAllCollection]

为什么document.all是这样的?既然document.all是一个对象(在我的浏览器中定义),typeof不应该返回"object",而不是"undefined"吗?

看看这个来自Html Spec

all属性必须返回根节点的HTMLAllCollectionDocument节点,其过滤器匹配所有元素。

all返回的对象有几个不寻常的行为:

  1. 用户代理必须表现得好像JavaScript中的ToBoolean抽象操作在给定所有返回对象时返回false。

  2. 用户代理必须像抽象相等比较算法一样,当给定all返回的对象时,返回true比较undefinednull的值。(使用严格相等比较算法和抽象相等与其他值(如字符串或对象)的比较不受影响)。

  3. 用户代理必须使JavaScript中的typeof操作符在应用于返回的对象时返回字符串"undefined"all .

第三个箱子是你的。

这样做的基本原理是与为旧浏览器设计的代码兼容,正如规范中的注释所解释的那样:

这种冲突的动机是希望与两类遗留内容兼容:一类使用document.all的存在作为检测遗留用户代理的方法,另一类只支持这些遗留用户代理并使用document.all对象而不首先测试其存在。

希望这对你有意义。

变通更新:

document.all !== undefined;
>> true /*otherwise*/ false

用户代理必须像抽象相等比较算法一样,当给定为所有返回的对象时,与未定义值和空值进行比较时返回true。

但自…

(使用严格相等比较算法的比较,以及与其他值(如字符串或对象)的抽象相等比较,不受影响。)

使用静态类型比较运算符(例如:=== | !==)检查HTMLAllCollection对象是否可用或存在于当前UA客户端中是完全安全的。动态类型比较运算符将继续按照规范的要求返回假缺席。

document.all != undefined;
>> false /*otherwise*/ false

一个解决方法(旧的)

"all" in document;
>> true /*otherwise*/ false

处理第三方代码时更复杂的方法是

delete document.all && "all" in document 
>> true /*otherwise*/ false