4

我正在使用基于 for(.. in ..) 和 hasOwnProperty 的递归函数来克隆对象,这在 IE 和 FF 中运行良好......但在 Chrome 中运行良好。

当使用 for(... in ...) 迭代对象的成员时,如果对象是 DOM 对象,Firefox 和 Chrome 会为 hasOwnProperty 提供不同的结果。

在 Chrome 控制台与 Firebug(FF) 中的控制台中键入以下内容会产生不同的结果:

var t = document.createElement("table");
var tr = t.insertRow(-1);
for(var p in tr) if(tr.hasOwnProperty(p)) console.log(p);

火狐输出:

构造函数
addEventListener

铬输出:

clientLeft
scrollHeight
firstElementChild
offsetParent
ch
offsetWidth
isContentEditable
hidden
previousElementSibling
parentElement
localName
children
ownerDocument
nodeValue
lastElementChild
rowIndex
offsetLeft
tagName
className
prefix
innerHTML
previousSibling
namespaceURI
id
childElementCount
innerText
scrollLeft
clientHeight
align
textContent
nextSibling
scrollWidth
offsetHeight
chOff
clientWidth
nodeName
style
lang
scrollTop
offsetTop
childNodes
baseURI
nextElementSibling
vAlign
sectionRowIndex
classList
title
firstChild
属性
数据集
outerText
单元
parentNode
clientTop
tabIndex
contentEditable
outerHTML
dir
lastChild
bgColor
nodeType
spellcheck
draggable

对于 hasOwnProeperty 标记为 true 的所有额外属性都导致我的代码中出现“无限/足够崩溃”的问题。有没有办法确定一个属性是否是一个内置的 DOM 对象属性?或者其他一些解决方案..

4

3 回答 3

4

最简单的解决方案是检查.cloneNode方法并使用它(如果存在)。

这意味着您的克隆方法将检查任何 DOM 节点并在其上使用预定义的 DOM 方法。这应该完全避免您的问题。

至于你的实际问题。似乎 Chrome 和 Firefox 在 HTMLTableRowElement (以及任何其他元素)的原型和对象上的内容上存在分歧。

console.dir(HTMLTableRowElement)在 Firefox 和 chrome 中进行比较。

在 Firefox 中,所有这些属性都存在于HTMLTableRowElement原型上。因为 chrome 原型只有几个方法。(delecteCellinsertCell)。

DOM 规范中没有说明 HTMLElements 的属性是应该在原型上还是在对象上定义,所以这只是你不应该依赖的东西。

无论哪种方式都可以使用.cloneNode,因为它是本机方法,因此比您可以用 JavaScript 编写的任何内容都更好/更快。

Chrome 伪实现:

function HTMLTableRowElement() {
    ...
    this.nextSibling = ...;
    this.nodeName = ...;
    this.nodeType = ...;
    ...
}

HTMLTableRowElement.prototype.deleteCell = function() { ... };
HTMLTableRowElement.prototype.insertCell = function() { ... };

火狐伪实现

function HTMLTableRowElement() {
    ...
}

HTMLTableRowElement.prototype.nextSibling = ...;
HTMLTableRowElement.prototype.nodeName = ...;
HTMLTableRowElement.prototype.nodeType = ...;
...
HTMLTableRowElement.prototype.deleteCell = function() { ... };
HTMLTableRowElement.prototype.insertCell = function() { ... };
于 2011-03-16T12:34:16.403 回答
1

我认为@Raynos 在他的回答中提供了一个很好的解决方案。至于为什么事情如此不同,我怀疑基本问题是 DOM 元素不是 JavaScript 对象——也就是说,它不以任何方式从 JavaScript“Object”类继承。DOM 元素由运行时提供,并且具有(通常)对 JavaScript 代码有意义的行为和语义,但它们在内部并不是真正的 JavaScript 对象。因此,对我来说,完全可以调用“hasOwnProperty”有点令人惊讶。

于 2011-03-16T12:39:25.147 回答
0

确定对象是否为 DOM 对象的最简单方法是检查该对象是否具有nodeNamenodeValuenodeType属性。

if ( tr.nodeType > 0 ) {
    // tr is a DOM object
} else {
    // tr is not a DOM object
}

所有 DOM 对象都实现Node 接口,因此包含上述属性。

于 2011-03-16T14:31:12.777 回答