为什么 document.all 是假的? [英] Why is document.all falsy?

查看:23
本文介绍了为什么 document.all 是假的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

document.all 是 DOM 中为假的非原始对象.

例如,这段代码什么都不做:

if (document.all) {警报(你好");}

谁能解释一下这是为什么?

解决方案

免责声明: 说:

<块引用>

all 属性必须返回一个以 Document 节点为根的 HTMLAllCollection,其过滤器匹配所有元素.

为所有人返回的对象有几个异常行为:

用户代理必须像 JavaScript 中的 ToBoolean() 操作符一样运行将 all 返回的对象转换为 false 值.

为了 ==!= 的目的,用户代理必须表现得好像JavaScript 中的运算符,为 all 返回的对象等于未定义值.

用户代理的行为必须使得 JavaScript 中的 typeof 操作符当应用于返回的对象时,返回字符串 'undefined'全部.

这些要求是对 JavaScript 的故意违反撰写本文时的最新规范(ECMAScript 第 5 版).JavaScript 规范要求 ToBoolean() 运算符将所有对象转换为 true 值,并且没有规定对于对象,就好像它们是 undefined 的目的一样某些运营商.这种违规行为的动机是为了与两类遗留内容的兼容性:一类使用document.all 的存在作为检测遗留用户代理的一种方式,以及一个只支持那些遗留的用户代理并使用document.all 对象,无需先测试其存在.

因此,document.all 是此 ECMAScript 规则的唯一官方例外.(在 Opera 中,document.attachEvent 等也是假的,但没有在任何地方指定.)

上面的文字解释了这样做的原因.但这里有一个在旧网页上很常见的示例代码片段,它将进一步说明这一点:

if (document.all) {//使用 `document.all` 的代码,适用于古老的浏览器} else if (document.getElementById) {//使用 `document.getElementById` 的代码,适用于现代"浏览器}

基本上,很长一段时间document.all 都是用这种方式来检测旧浏览器的.因为 document.all 首先被测试,提供这两个属性的更现代的浏览器仍然会在 document.all 代码路径中结束.在现代浏览器中,我们当然更喜欢使用 document.getElementById,但是由于大多数浏览器仍然具有 document.all(出于其他向后兼容性原因)document.all 为真,则永远不会访问 >else.如果代码写得不同,这不会是一个问题:

if (document.getElementById) {//使用 `document.getElementById` 的代码,适用于现代"浏览器} else if (document.all) {//使用 `document.all` 的代码,适用于古老的浏览器}

但遗憾的是,很多现有的代码都是反过来的.

解决这个问题的最简单方法是在仍然模仿它的浏览器中简单地使 document.all 为假.

document.all is a non-primitive object in the DOM that is falsy.

For example, this code doesn't do anything:

if (document.all) {
    alert("hello");
}

Can someone explain why this is?

解决方案

Disclaimer: I’m the guy who tweeted the question that led to this thread :) It was a question I would ask and answer in my Front-Trends talk. I wrote that tweet 5 minutes before going on stage.


The question I was asking is the following.

The ECMAScript spec defines ToBoolean() as follows:

As you can see, all non-primitive objects (i.e. all objects that aren’t a boolean, a number, a string, undefined, or null) are truthy as per the spec. However, in the DOM, there is one exception to this — a DOM object that is falsy. Do you know which one that is?

The answer is document.all. The HTML spec says:

The all attribute must return an HTMLAllCollection rooted at the Document node, whose filter matches all elements.

The object returned for all has several unusual behaviors:

The user agent must act as if the ToBoolean() operator in JavaScript converts the object returned for all to the false value.

The user agent must act as if, for the purposes of the == and != operators in JavaScript, the object returned for all is equal to the undefined value.

The user agent must act such that the typeof operator in JavaScript returns the string 'undefined' when applied to the object returned for all.

These requirements are a willful violation of the JavaScript specification current at the time of writing (ECMAScript edition 5). The JavaScript specification requires that the ToBoolean() operator convert all objects to the true value, and does not have provisions for objects acting as if they were undefined for the purposes of certain operators. This violation is motivated by a desire for compatibility with two classes of legacy content: one that uses the presence of document.all as a way to detect legacy user agents, and one that only supports those legacy user agents and uses the document.all object without testing for its presence first.

So, document.all is the only official exception to this ECMAScript rule. (In Opera, document.attachEvent etc. are falsy too, but that’s not specced anywhere.)

The above text explains why this was done. But here’s an example code snippet that’s very common on old web pages, and that will illustrate this further:

if (document.all) {
  // code that uses `document.all`, for ancient browsers
} else if (document.getElementById) {
  // code that uses `document.getElementById`, for "modern" browsers
}

Basically, for a long time document.all was used in this way to detect old browsers. Because document.all is tested first though, more modern browsers that offer both properties, would still end up in the document.all code path. In modern browsers, we’d prefer to use document.getElementById, of course, but since most browsers still have document.all (for other backwards compatibility reasons) the else would never be accessed if document.all was truthy. Had the code been written differently, this wouldn’t be a problem:

if (document.getElementById) {
  // code that uses `document.getElementById`, for "modern" browsers
} else if (document.all) {
  // code that uses `document.all`, for ancient browsers
}

But sadly, a lot of existing code does it the other way around.

The simplest fix for this problem is to simply make document.all be falsy in browsers that still mimic it.

这篇关于为什么 document.all 是假的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆