我尝试通过以下代码检查属性clientHeight:
document.documentElement != null && document.documentElement.hasOwnProperty('clientHeight')
,因为document.documentElement.hasOwnProperty('clientHeight'),结果为false
但是当我通过'clientHeight' in document.documentElement
检查它时它返回true。在Chrome,FF,Opera都运行良好。这种行为的原因是什么?
答案 0 :(得分:2)
没有回答你的问题(这是什么原因),但仍想分享,所以从评论中延伸:
具有属性的对象不一定意味着该属性由该对象“拥有”;它可以在原型链中。
检查一下(在Chrome DevTools控制台中):
Object.create({"foo":"bar"}).hasOwnProperty("foo")
false
"foo" in Object.create({"foo":"bar"})
true
正如您所看到的,foo
确实存在于创建的对象中,但它不是由对象“拥有”的,只是位于原型链中。
当谈到DOM原型时,事情可能会有点复杂,因为不同的平台可能会以不同的方式实现相同的东西。
根据MDN,clientHeight
定义了Element.prototype
,所以
[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
不是可构造的,因此不严格,完全可克隆。