我在试图回答这个问题时遇到了困难:解释JavaScript中的奇怪行为。在研究过程中,我发现直接分配给主机对象的事件处理程序呈现出一种奇怪的行为:它们可以作为对象的属性进行访问,但不知何故,它们似乎不是实际属性。
例如,如果我在全局范围内定义一个变量,它看起来像 window
的任何其他属性:
var foo = "foo";
console.log(Object.getOwnPropertyDescriptor(window, 'foo'));
// Object {value: "foo", writable: true, enumerable: true, configurable: false}
如果我只分配给window.foo
,或者如果我创建一个隐含的全局,我会得到相同的输出(但出于已知原因,[[可配置]]将被true
;当然,这在严格模式下不起作用)。但是,如果我尝试通过分配给window.onsomething
来添加事件处理程序,则无法使用Object.getOwnPropertyDescriptor
读取该属性(尽管它仍然可以在window.onsomething
下访问):
window.onresize = function onresize(e) {
console.log('rsz', e);
}
console.log(window.onresize); // function onresize(){...}
console.log(Object.getOwnPropertyDescriptor(window, 'onresize')); // undefined
浏览器如何处理这样分配的事件处理程序?我怀疑这个问题的答案也是另一个问题的答案。
window
对象是 Window
构造函数的实例,该构造函数onresize
作为其原型的一部分。
尝试记录window
并启用show own properties only
选项。 onresize
将不存在,因为它是从Window
继承而来的。这就是为什么getOwnProperty
不接收它的原因,因为它只返回对象拥有的属性的描述符,而不是源自原型链的属性的描述符。
如果你检查 MDN 文档的getOwnPropertyDescriptor
,它只报告直接在该对象上的属性,而不是在原型链中的属性。
例如,它适用于:
Object.getOwnPropertyDescriptor(window, 'location')
但不适用于:
Object.getOwnPropertyDescriptor(window, 'onresize')
可能是因为onresize
在窗口继承的内容上(因此在原型链中),而不是在实际的窗口对象本身上。