IE中使用setAttributeNode设置td的colspan属性报错是否为Bug?
结论:这是IE的浏览器Bug
这绝对是旧版IE的DOM实现Bug,而且是那种典型的、和标准规范不符的怪异行为,咱们一步步拆解来看:
先确认核心现象
首先是触发报错的代码:
try { var dom = document.createElement("td"); var attribute = document.createAttribute("colspan"); // rowspan表现一致 dom.setAttributeNode(attribute); } catch (err) { console.log(err.message); // 输出"Member not found" }
但下面这两段代码却完全正常:
// 给<tr>挂载colspan属性节点,无报错 try { var dom = document.createElement("tr"); var attribute = document.createAttribute("colspan"); dom.setAttributeNode(attribute); } catch (err) { console.log(err.message); } // 给<td>挂载style属性节点,无报错 try { var dom = document.createElement("td"); var attribute = document.createAttribute("style"); dom.setAttributeNode(attribute); } catch (err) { console.log(err.message); }
还有更诡异的交互:
var attribute = document.createAttribute("colspan"); var dom = document.createElement("td"); attribute.value = "5"; console.log(attribute.value); // 输出"5" try { dom.setAttributeNode(attribute); // 抛出错误 } catch (err) {} console.log(dom.outerHTML); // 输出"<td></td>" console.log(attribute.value); // 输出undefined attribute.value = "5"; console.log(dom.outerHTML); // 输出"<td colspan=\"5\"></td>" console.log(attribute.value); // 输出"5"
为什么这是Bug?
按照DOM标准规范:
colspan是<td>/<th>的合法标准属性,不存在属性与元素不兼容的问题(比如给<div>加colspan才是不合法,但这里是td本身就支持的属性)document.createAttribute创建的是通用属性节点,只要目标元素支持该属性,setAttributeNode就应该成功完成挂载- 报错后出现的“属性节点value被清空、重新赋值后自动同步到td的outerHTML”完全不符合规范——属性节点挂载失败后,它和元素应该是完全独立的,不应该有任何隐性绑定关系
背后的可能原因
旧版IE对表格元素的属性有特殊的“私有处理”:它把colspan、rowspan这类表格属性当成了元素的原生对象属性(property),而不是普通的HTML属性(attribute)。当你用createAttribute创建属性节点并尝试挂载时,IE的引擎试图把这个属性节点映射到对应的原生property,但内部处理逻辑出了问题,导致抛出错误。
而给<tr>挂载colspan时,因为<tr>本身不支持这个属性,IE反而把它当成普通的自定义属性处理,所以不会报错;style是所有元素都支持的通用属性,处理逻辑正常,自然也不会出问题。
那个诡异的交互更是Bug的铁证:挂载失败后属性节点和元素居然还保持了隐性关联,这完全违背了DOM属性节点的生命周期规则——只有成功挂载的属性节点才会和元素绑定,失败的话两者应该毫无关系。
内容的提问来源于stack exchange,提问作者nick zoum
相关产品推荐
相关产品推荐

