javascript 为什么 document.all 是假的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10350142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is document.all falsy?
提问by anonymous coward
document.all
is a non-primitive object in the DOM that is falsy.
document.all
是 DOM 中为假的非原始对象。
For example, this code doesn't do anything:
例如,此代码不执行任何操作:
if (document.all) {
alert("hello");
}
Can someone explain why this is?
有人可以解释这是为什么吗?
回答by Mathias Bynens
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-Trendstalk. I wrote that tweet 5 minutes before going on stage.
免责声明:我是在推特上发布导致此线程的问题的人:)这是我会在我的前沿趋势演讲中提出和回答的问题。我在上台前 5 分钟写了这条推文。
The question I was asking is the following.
我问的问题如下。
The ECMAScript spec defines ToBoolean()
as follows:
ECMAScript 规范定义ToBoolean()
如下:
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?
如您所见,所有非原始对象(即所有不是布尔值、数字、字符串undefined
、 或 的对象null
)都是符合规范的。然而,在 DOM 中,有一个例外——一个 DOM 对象是假的。你知道那是哪一个吗?
The answer is document.all
. The HTML specsays:
答案是document.all
。HTML 规范说:
The
all
attribute must return anHTMLAllCollection
rooted at theDocument
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 forall
to thefalse
value.The user agent must act as if, for the purposes of the
==
and!=
operators in JavaScript, the object returned forall
is equal to theundefined
value.The user agent must act such that the
typeof
operator in JavaScript returns the string'undefined'
when applied to the object returned forall
.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 thetrue
value, and does not have provisions for objects acting as if they wereundefined
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 ofdocument.all
as a way to detect legacy user agents, and one that only supports those legacy user agents and uses thedocument.all
object without testing for its presence first.
该
all
属性必须返回一个HTMLAllCollection
以Document
节点为根的节点,其过滤器匹配所有元素。为所有人返回的对象有几个不寻常的行为:
用户代理必须采取行动,就好像
ToBoolean()
在JavaScript操作转换为返回的对象all
的false
值。就 JavaScript中的
==
and!=
运算符而言,用户代理必须表现得好像返回的对象all
等于该undefined
值。用户代理的行为必须使
typeof
JavaScript中的运算符在'undefined'
应用于为 返回的对象时 返回字符串all
。这些要求故意违反了撰写本文时的 JavaScript 规范(ECMAScript 第 5 版)。JavaScript 规范要求
ToBoolean()
运算符将所有对象转换为true
值,并且没有规定对象的行为就好像它们是undefined
为了某些运算符的目的。这种违规的动机是希望与两类遗留内容兼容:一种使用存在document.all
作为检测遗留用户代理的方式,另一种只支持那些遗留用户代理并使用document.all
对象而不先测试其存在.
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.)
因此,document.all
这是 ECMAScript 规则的唯一官方例外。(在 Opera 中,document.attachEvent
等等也是假的,但没有在任何地方指定。)
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:
基本上,很长一段时间document.all
都是用这种方式来检测旧浏览器的。因为document.all
首先进行测试,提供这两个属性的更现代的浏览器仍然会在document.all
代码路径中结束。在现代浏览器中,我们当然更喜欢使用document.getElementById
,但由于大多数浏览器仍然具有document.all
(出于其他向后兼容性原因)else
如果document.all
为真,则永远不会被访问。如果代码的编写方式不同,这不会成为问题:
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
在仍然模仿它的浏览器中简单地 make be falsy。
回答by Konrad Borowski
In short, it's to make BOTH of these code samples work. Browsers have to do this so that old web pages will continue to work.
简而言之,就是让这两个代码示例都能正常工作。浏览器必须这样做,这样旧的网页才能继续工作。
Sample 1
示例 1
// Internet Explorer
if (document.all) {
useActiveX()
}
// Netscape Navigator
else {
useOldButStillWorkingCode()
}
Sample 2
样本 2
document.all.output.innerHTML = 'Hello, world!'
回答by Bergi
Modern browsers don't implement this outdated thing any more. It was introduced by IE, but most of the others "shim" it to be compatible.
现代浏览器不再实现这个过时的东西。它是由 IE 引入的,但其他大多数“填充”它以兼容。
To make browser detection possible (back in the old days you could tell IE apart from NN by testing for document.all
) while supporting document.all syntax, other browsers made the "weird" implementation that typeof document.all
returns undefined.
为了document.all
在支持 document.all 语法的同时使浏览器检测成为可能(在过去,您可以通过测试将 IE 与 NN 区分开来),同时支持 document.all 语法,其他浏览器制作了typeof document.all
返回 undefined的“怪异”实现。
Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false
Before FF dropped support for it, it also showed weird behaviour as stated in this message. You may find more internals in Mozilla bug #412247.
在 FF 放弃对它的支持之前,它也表现出如此消息中所述的奇怪行为。您可能会在Mozilla 错误 #412247 中找到更多内部结构。
There is also a very long threadin the W3C mailing list archive, beginning with http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html
在 W3C 邮件列表存档中还有一个很长的线程,以http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html开头
回答by GillesC
document.all is not the only object that is falsy. Another question was posted about this and as the fiddle example in the answer show there is many falsy object in document. The amount varies depending on the browser used.
document.all 不是唯一一个为假的对象。关于此问题发布了另一个问题,正如答案中的小提琴示例所示,文档中有许多虚假对象。金额因使用的浏览器而异。
See this question All objects in JavaScript are truthy per the spec, but in the DOM one non-primitive object is not. Which?
请参阅此问题JavaScript 中的所有对象都符合规范,但在 DOM 中,非原始对象不是。哪个?
And a fiddle that display all falsy object of document http://jsfiddle.net/UTNkW/
以及显示文档http://jsfiddle.net/UTNkW/ 的所有虚假对象的小提琴
回答by D. Pardal
ES2019 Update
ES2019 更新
There is now an [[IsHTMLDDA]] internal slotfor objects:
现在有一个用于对象的[[IsHTMLDDA]] 内部插槽:
An [[IsHTMLDDA]] internal slot may exist on implementation-defined objects. Objects with an [[IsHTMLDDA]] internal slot behave like
undefined
in the ToBoolean and Abstract Equality Comparison abstract operations and when used as an operand for thetypeof
operator.
[[IsHTMLDDA]] 内部插槽可能存在于实现定义的对象上。具有 [[IsHTMLDDA]] 内部槽的对象
undefined
在 ToBoolean 和抽象相等比较抽象操作中的行为以及用作typeof
运算符的操作数时的行为。
The HTML Standard has also been updated to add that internal slot for objects that implement the HTMLAllCollection
interface:
HTML 标准也已更新,为实现HTMLAllCollection
接口的对象添加了内部插槽:
Objects that implement the HTMLAllCollection interface are legacy platform objects with an additonal [[Call]] internal method described in the section below. They also have an [[IsHTMLDDA]] internal slot.
实现 HTMLAllCollection 接口的对象是具有附加 [[Call]] 内部方法的旧平台对象,如下一节所述。它们还有一个 [[IsHTMLDDA]] 内部插槽。
The reason for this madness is specified in this note in the HTML Standard:
这种疯狂的原因在 HTML 标准的这个注释中指定:
These special behaviors are 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 thedocument.all
object without testing for its presence first.
这些特殊行为的动机是希望与两类遗留内容兼容:一种使用存在
document.all
作为检测遗留用户代理的方式,另一种只支持那些遗留用户代理并使用document.all
对象而不测试其存在第一的。
So basically the standard wants to be compatible with these two types of code:
所以基本上标准想要兼容这两种类型的代码:
Code that checks if it is running inside Internet Explorer to use its non-standard features, like
document.all
and Activex;if (document.all) { useActiveXStuff(); }
Code that assumes it's running inside Internet Explorer and uses
document.all
.document.all["my-button"].onclick = function () { alert("hi"); };
检查它是否在 Internet Explorer 中运行以使用其非标准功能(如
document.all
Activex)的代码;if (document.all) { useActiveXStuff(); }
假定它在 Internet Explorer 中运行并使用
document.all
.document.all["my-button"].onclick = function () { alert("hi"); };