2

私はこのコードでプロパティ clientHeight をチェックしようとします:

document.documentElement != null && document.documentElement.hasOwnProperty('clientHeight')

document.documentElement.hasOwnProperty('clientHeight') のために結果は false ですが、チェックすると'clientHeight' in document.documentElementtrue が返されます。Chrome、FF、Opera ではすべて正常に動作します。この動作の理由は何ですか?

4

1 に答える 1

2

あなたの質問には答えませんが(これの理由は何ですか)、それでも共有したいので、コメントから拡張します:

プロパティを持つオブジェクトは、プロパティがそのオブジェクトによって「所有」されていることを必ずしも意味しません。プロトタイプチェーンに含めることができます。

これについて確認してください(Chrome DevToolsコンソールで):

Object.create({"foo":"bar"}).hasOwnProperty("foo")
false
"foo" in Object.create({"foo":"bar"})
true

ご覧のfooとおり、作成されたオブジェクトには存在しますが、オブジェクトによって「所有」されておらず、プロトタイプ チェーンにあるだけです。

DOM プロトタイプについて話すと、プラットフォームが異なれば同じものを異なる方法で実装する可能性があるため、状況は少し複雑になる可能性があります。

MDNによると、clientHeightで定義されElement.prototypeているので、

Firefoxのコンソールで、私は得ました:

[17:09:55.701] document.documentElement.hasOwnProperty("clientHeight")
[17:09:55.702] false
--
[17:10:19.894] "clientHeight" in document.documentElement
[17:10:19.895] true

しかし、Opera Dragonfly コンソールでは、次のようになりました。

>>> document.documentElement.hasOwnProperty("clientHeight")
true
>>> "clientHeight" in document.documentElement
true

そしてChrome DevToolsコンソールで、私は得ました:

document.documentElement.hasOwnProperty("clientHeight")
true
"clientHeight" in document.documentElement
true

(今テストする IE10 はありませんが、私の記憶が正しければ、IE10 は Firefox スタイルに従っています)

したがって、ChromeとOperaではclientHeight、ではなく「要素ごと」に定義されているようElement.prototypeです。もう少し進むと、次のことがわかります。

Object.getPrototypeOf(document.documentElement)
HTMLHtmlElement {insertAdjacentHTML: function, insertAdjacentText: function, click: function, insertAdjacentElement: function, getAttribute: function…}
    constructor: function HTMLHtmlElement() { [native code] }
    __proto__: HTMLElement
        click: function click() { [native code] }
        constructor: function HTMLElement() { [native code] }
        insertAdjacentElement: function insertAdjacentElement() { [native code] }
        insertAdjacentHTML: function insertAdjacentHTML() { [native code] }
        insertAdjacentText: function insertAdjacentText() { [native code] }
        __proto__: Element

あなたの問題に関しては、あなたが達成しようとしていることは何でも、この「標準」に依存せず、機能検出を使用してください。


JS でオブジェクトを複製しようとしたときに、この動作に最初に気付きました。

ClientRectオブジェクトのクローンを作成しようとするとき(例: document.body.getBoundingClientRect())、少し凝りたいときは、最初に次のことを試しました。

var cloned={};
if(cloned.__proto__) {
    cloned.__proto__=source.__proto__;
}
for(var i in source) {
    if(Object.prototype.hasOwnProperty.call(source,i)){
        cloned[i]=source[i];
    }
}

clonedChrome では問題なく動作しますが、Firefox では{width:undefined,height:undefined...}. だから私はこれに変更しfor..inました:

for(var in source) {
    cloned[i]=source[i];
}

iFirefox では、これらの 6 つのプロパティが読み取り専用であるため、最初に例外が発生しました。

ClientRectいくつかの失敗の後、Firefox では構築可能ではないため、厳密には完全に複製可能ではないという結論に達しました。

于 2013-05-29T09:36:56.497 に答える