【问题标题】:Are directly assigned event handlers actual object properties?直接分配的事件处理程序是实际的对象属性吗?
【发布时间】:2012-12-10 21:54:14
【问题描述】:

我在试图回答这个问题时遇到了困难:Explaining odd behavior in javascript。在研究过程中,我发现直接分配给宿主对象的事件处理程序呈现出一种奇怪的行为:它们可以作为对象的属性进行访问,但不知何故,它们似乎不是实际的属性。

例如,如果我在全局范围内定义一个变量,它看起来就像window 的任何其他属性:

​var foo = "foo";
console.log(Object.getOwnPropertyDescriptor(window, 'foo'));
// Object {value: "foo", writable: true, enumerable: true, configurable: false} 

如果我只是分配给window.foo,或者如果我创建一个隐含的全局(但由于已知原因,[[Configurable]] 将是true,我会得到相同的输出;当然,那不会t 在严格模式下工作)。但是,如果我尝试通过分配给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

浏览器如何处理这样分配的事件处理程序?我怀疑这个问题的答案也是另一个问题的答案。

【问题讨论】:

  • 你真正想解决什么问题?宿主对象上的属性可能与纯 javascript 属性的行为不同(在不同的浏览器中)。
  • 可能在这里看到一些线索:developer.mozilla.org/en-US/docs/JavaScript/Reference/…
  • 说实话,没有。我试图回答链接的问题,但找不到让我信服的解释。这个问题是在我研究期间提出的。

标签: javascript javascript-events event-handling


【解决方案1】:

window 对象是Window 构造函数的一个实例,该构造函数将onresize 作为其原型的一部分。

尝试记录window 并启用show own properties only 选项。 onresize 不会出现,因为它继承自 Window。这就是getOwnProperty 不接受它的原因,因为它只返回对象拥有的属性的描述符,而不是源自原型链的那些。

【讨论】:

  • 感谢 Asad,这回答了我的问题,也是我试图回答的问题。完全有道理。
  • @bfavaretto dfreeman 提出了一个很好的观点。我的答案和另一个答案实际上并没有正确回答您的问题。
  • 我现在正在调查。另一方面,您的答案非常适合我试图回答的问题。在那种情况下,它似乎真的是一个阴影的情况。如果我们发现它不是,我会把它收回 - 再一次(叹气)。
  • @bfavaretto 问题是 non-shadowing 的情况。当您重新分配onresize 时,它应该创建一个对window 唯一的新属性,它是一个“自己的”属性。我想事件处理程序属性的处理方式不同。
  • Asad,请参阅我最近对 ​​jfriend 回答的评论。最后一个链接可以解释奇怪的非阴影行为,如果那是浏览器真正实现的东西。我重新接受了这个答案,因为它确实回答了我在标题中提出的问题,尽管这个问题还有更多 –可能是由于依赖于实现的因素。
【解决方案2】:

如果您检查MDN documentation for getOwnPropertyDescriptor,它只会报告直接在该对象上的属性,而不是在原型链中。

例如,它适用于:

Object.getOwnPropertyDescriptor(window, 'location')

但不适用于:

Object.getOwnPropertyDescriptor(window, 'onresize')

可能是因为onresize 在窗口继承自的东西上(因此在原型链中),而不是在实际的窗口对象本身上。

【讨论】:

  • 不过,它的意义远不止于此。 window.toString = function() { return "foo"; }; Object.getOwnPropertyDescriptor(window, 'toString'); 实际上,上面将返回一个“toString”的描述符,即使原始定义位于原型链中更高的对象上。
  • 我读到了,但我不知道onresize 在原型链上。谢谢。
  • 所以这确实回答了我的问题和另一个问题。出于某种原因,我认为它会更晦涩难懂,但这完全有道理。
  • @dfreeman 我明白你的意思,为什么不创建一个新的“自己的”onresize 属性来隐藏原型继承的属性?
  • @dfreeman 关于window.toString 的情况,在不同的浏览器上测试时更加奇怪:jsfiddle.net/XMUKn。至于事件处理程序:分配给window.onresize 显然确实改变了Window.prototype.onresize(参见jsfiddle.net/asHP7)。也许是因为这个:w3.org/html/wg/drafts/html/master/…
猜你喜欢
  • 1970-01-01
  • 2016-08-27
  • 1970-01-01
  • 2021-07-13
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多