ie10中clientHeight的奇怪行为 [英] Strange behaviour of clientHeight in ie10

查看:214
本文介绍了ie10中clientHeight的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试通过以下代码检查属性clientHeight:

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

,由于document.documentElement.hasOwnProperty('clientHeight'),结果为false 但是当我通过'clientHeight' in document.documentElement对其进行检查时,它返回true.在Chrome,FF,Opera中一切正常.这种行为的原因是什么?

解决方案

未回答您的问题(原因是什么),但仍想分享,因此从评论中扩展:

具有属性的对象不一定意味着该对象拥有"属性;它可以在原型链中.

对此进行检查(在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];
    }
}

在Chrome中工作正常,但在Firefox中,cloned看起来像{width:undefined,height:undefined...}.因此,我将for..in更改为此:

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

在Firefox中,这在最初的i给了我一个例外,因为这6个属性是只读的.

经过几次失败后,我得出结论,Firefox中的ClientRect是不可构造的,因此不能严格完全克隆.

I try to check property clientHeight by this code:

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

and the result is false because of document.documentElement.hasOwnProperty('clientHeight') but when i check it by 'clientHeight' in document.documentElement it return true. In Chrome,FF,Opera all works fine. What is the reason for this behavior?

解决方案

Not answering your question (what is the reason for this), but still want to share, so extending from comment:

An object with a property doesn't necessary mean that property is "owned" by that object; it can be in the prototype chain.

Check about this (in Chrome DevTools console):

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

So as you can see, foo does exist in the created object, but it's not "owned" by the object, just sits in the prototype chain.

When talk about DOM prototype, things can be a little bit more complicated as different platform may implement the same thing differently.

According to MDN, clientHeight is defined in Element.prototype, so

in Firefox's console, I got:

[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

but in Opera Dragonfly console, I got:

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

and in Chrome DevTools console, I got:

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

(No IE10 for me to test right now, but if I remember correctly, IE10 follows Firefox style)

So it seems in Chrome and Opera, clientHeight is defined "per element", not in Element.prototype. Go a little further and you can see:

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

As to your problem, I would say, whatever you're trying to accomplish, don't depend on this "standard", use feature detection.


I first noticed this behavior when I tried to clone object in JS.

When trying to clone a ClientRect object (e.g. document.body.getBoundingClientRect()), when I want to go a little bit fancy, I first tried:

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];
    }
}

In Chrome it works fine, but in Firefox the cloned looks like {width:undefined,height:undefined...}. So I changed the for..in to this:

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

In Firefox this gave me an Exception at the very first i because those 6 properties are read only.

After some failure I concluded that ClientRect in Firefox is not constructible, so not strictly, perfectly cloneable.

这篇关于ie10中clientHeight的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆