平常我们在js的类型转换学习过程中,经常能看到对象转换成布尔值的例子,不论是空对象{}
还是原型为null
的对象,它们在转换成布尔值之后都为true
。那么,对象真的都为true
吗?
我们先看看ECMA -262(ECMAScript)规范中针对布尔类型转换是怎么说的(不知道ECMAScript的同学可以先去了解一下):
前两步没啥好说的的,undefined、null、NaN、0、空字符串都为false。重点是这个被替换掉的第三点,我们跳转过去看看:
翻译过来就是:如果参数是一个对象并且参数有[[IsHTMLDDA]]
内置插槽,就返回false
。
问题来了,[[IsHTMLDDA]]
是什么?
[[IsHTMLDDA]]
插槽是采用ECMA规范的语言在其内部定义的,外部(比如js)无法获取到这个插槽。根据描述,所有拥有[[IsHTMLDDA]]
插槽的对象在转换成布尔值,宽松相等的比较(==)和使用typeof
操作符时都应该表现的像undefined
。
下面是其宽松比较和使用typeof
操作符相关的规范
那么,什么对象拥有[[IsHTMLDDA]]
插槽呢?这个在规范中也提到了:
除了document.all
以外没有其他已知的对象拥有此插槽,也无法手动创建一个插槽。做个测试:
确实和规范里说的一样。
所以为什么document.all
这么特殊?简单来说是历史原因,document.all
已经被废弃了,取而代之的是document.getElementById
、document.querySelector
等方法,但是为了兼容老的浏览器,就不得不写if (document.all) {xxx} else {document.getElementById(xxx)}
这种代码,然而某些现代浏览器依然保留了document.all
,导致优先进入了前一个if
分支,于是W3C听从了大家的建议,将document.all
的规范定义成了如今这样,这样一来老的浏览器判断document.all
为true
,但是新的浏览器不论有没有保留document.all
,直接判断为false
了。
参考: