IE下JS childNodes属性的疑惑



<div id="test"> <i>test</i> </div>
var test = document.getElementById("test");

alert(test.childNodes[1].nodeType);

IE 下弹出 3,难道 i 标签后面的空文本也算进去了
IE 不是会忽略空文本节点的吗?i 标签前面的空文本就没算进去啊!
但是吧 i 标签换成其他的 div, p 标签之类就正常的,
但是 i 标签,em 标签,b 标签之类的改变字体样式的标签就会出现这个问题,
这是为什么呢,左右不对称啊

阅读 6.9k
2 个回答

W3Help处有详细的实验过程。

要注意到,IE下,会影响到渲染的空文本节点都没有忽略,比如说,行内标签之间的空白节点。在W3C标准中,行内标签之间的空白节点,必须根据white-space属性进行判断,影响渲染。


下面详细解释会影响到渲染的空文本节点。让我们从空白符开始吧。

W3C 9.1 White space 规定了以下字符为空白符:

  • ASCII 空格 &#x0020;
  • ASCII 制表符 &#x0009;
  • ASCII 换页符 &#x000C;
  • 零宽度空格 &#x200B;
  • 折行(line-break) &#x000D;&#x000A;
通常情况下,对于多个连续的空白符(空格,换行符,回车符等),浏览器会将他们合并为一个空白符。CSS 中由white-space这个属性来控制:
  • normal:默认处理方式。
  • pre:用等宽字体显示预先格式化的文本,不合并文字间的空白距离,当文字超出边界时不换行。可查阅 pre 对象
  • nowrap:强制在同一行内显示所有文本,直到文本结束或者遭遇 br 对象。
  • pre-wrap:用等宽字体显示预先格式化的文本,不合并文字间的空白距离,当文字碰到边界时发生换行。
  • pre-line:保持文本的换行,不保留文字间的空白距离,当文字碰到边界时发生换行。
——《inline-block 前世今生

在接下来的 W3C 16.6.1 The 'white-space' processing model 里讲到空白符是如何参与渲染策略的:

下面是我对标准的翻译

对于每个inline元素(包括匿名的inline元素),下列步骤被执行:

  1. white-space设为normal, nowrappre-lineU+000A(linefeed)周边的U+0009(tab)、U+000D(carriage return)、U+0020(space)被舍弃
  2. white-space被设为prepre-wrap,任何不被元素边界破坏的空格序列U+0020被当做不折行的空格。然而,对于pre-wrap属性来说,在空格序列末尾有可能出现折行
  3. white-space设为normalnowrap,在不一样的UA相关的上下文中,linefeed字符可能被当做空白符中的任意一个,或者没有字符(因此而不被渲染)
  4. white-space设为normal, nowrappre-line,tab字符被转化为空格;同时任何空白符之后的空白符——甚至是inline元素之前的white-space,只要该white space被应用了white-space:normal | nowrap | pre-line——会被移除

然后内联元素被排版下来,根据bidi信息被重新排序,然后按照white-space属性被包裹(wrap,可以理解为放进块级元素内部)起来。包裹过程中,按照white-space属性考虑是否折行。

每行的排版过程中:

  1. white-space设为normal, nowrappre-line,行首的空格被舍弃
  2. 所有的tab被渲染为一行的水平位移,直到下一个tab stop处。tab stop出现在每个块级的content-edge开始的每8个空格处
  3. white-space设为normal, nowrappre-line,行尾的空格被舍弃
  4. white-space设为pre-wrap,行尾的空格和tab可能被UA折叠

浮动定位和绝对定位元素没有新的折行可能。


IE对空白符的解析,正好避免了可能影响到渲染的部分,去掉的空白符是空格在渲染环节被舍弃的部分(非全部,比如行末空白符就被保留了)。

两个过程本不应该混淆:决定空白符是否出现在DOM树中的这一步,发生在构建DOM树的阶段;决定空白符是否被渲染的这一步,发生在构建Rendering树阶段。
这个bug的影响,在于DOM而非CSS,具体而言,遍历childNodes时会有浏览器差异,做额外的判断即可。对于渲染没有区别。

P.S. M$的C++程序员对性能的焦渴导致他们在HTML parse阶段也有意识地控制DOM树大小?

div/p属于块状元素,i/em/b等等属于内联元素;
所有HTML元素都有一个dispaly属性并且有默认值,div/p的display默认值是block,而后面那几个的display默认值是inline;
IE处理两类元素的方式不一样,所以你发现的问题就是答案;只是没意识到它们有默认dispaly值而已;

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题