为什么document.all麻痹? [英] Why is document.all falsy?

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

问题描述

document.all 是DOM中的非基本对象,是假的。



例如,此代码不执行任何操作:

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

有人可以解释为什么会这样吗?

解决方案

免责声明: 说:


所有属性必须返回 HTMLAllCollection Document 节点为根,其过滤器匹配所有元素。



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



用户代理必须像JavaScript $中的 ToBoolean()运算符一样b $ b将为所有返回的对象转换为 false 值。



对于 == != $,用户代理必须表现得好像一样在JavaScript中的b $ b运算符,为所有返回的对象等于
未定义值。 / p>

用户代理必须采取行动,以使JavaScript
中的 typeof 运算符返回字符串 '未定义'当应用于返回的对象
全部



这些要求是在撰写本文时故意违反JavaScript
规范(ECMAScript第5版)。
JavaScript规范要求 ToBoolean()运算符
将所有对象转换为 true 对于
某些运营商而言,对象的行为就像 undefined 一样没有规定
。这种违规行为的动机是希望
与两类遗留内容兼容:一种使用$ b $ c存在 document.all 的方式检测旧版用户代理,
仅支持这些旧版用户代理,并使用
document.all 对象,而不先测试其存在。


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



以上文字解释了为什么这样做。但这是一个在旧网页上非常常见的示例代码段,这将进一步说明这一点:

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

基本上,很长一段时间文件.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天全站免登陆