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);

Firefox の出力:

コンストラクター
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
attributes
dataset
outerText
cells
parentNode
clientTop
tabIndex
contentEditable
outerHTML
dir
lastChild
bgColor
nodeType
スペルチェック
ドラッグ可能

hasOwnProeperty に対して true としてフラグが立てられたすべての余分なプロパティは、私のコードで「無限/十分にクラッシュする」再帰を引き起こしています。プロパティがDOMオブジェクトプロパティに組み込まれているかどうかを判断する方法はありますか? または他の解決策..

4

3 に答える 3

4

これに対する最も簡単な解決策は、.cloneNodeメソッドを確認し、存在する場合はそれを使用することです。

これは、複製メソッドが DOM ノードをチェックし、定義済みの DOM メソッドを使用することを意味します。これにより、問題を完全に回避できます。

あなたの実際の問題について。Chrome と Firefox は、プロトタイプに属するものと HTMLTableRowElement (およびその他の要素) のオブジェクトに属するものについて意見が一致していないようです。

console.dir(HTMLTableRowElement)firefox と chrome の両方で比較してください。

Firefox では、これらすべてのプロパティがHTMLTableRowElementプロトタイプに存在します。クロムプロトタイプにはいくつかのメソッドしかありません。(delecteCellおよびinsertCell)。

DOM 仕様のどこにも、HTMLElements のプロパティをプロトタイプで定義する必要があるか、オブジェクトで具体的に定義する必要があるかは記載されていないため、これは依存すべきではありません。

どちら.cloneNodeの方法でも使用できます。これはネイティブ メソッドであるため、JavaScript で記述できるものよりも優れている/高速であるためです。

Chrome 疑似実装:

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

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

Firefox 疑似実装

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 の「オブジェクト」クラスをまったく継承していないことにあるのではないかと思います。DOM 要素はランタイムによって提供され、(通常は) JavaScript コードにとって意味のある動作とセマンティクスを備えていますが、内部的には実際には JavaScript オブジェクトではありません。したがって、私にとっては、「hasOwnProperty」を呼び出すことができるのは少し驚くべきことです。

于 2011-03-16T12:39:25.147 に答える
0

The easiest way to determine whether or not an object is a DOM object would be to check if that object has the nodeName, nodeValue or nodeType properties.

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

All DOM objects implement the Node interface and therefore contain the above mentioned properties.

于 2011-03-16T14:31:12.777 に答える