Google Chrome(build 84)破坏了Javascript事件(Uncaught TypeError:ti



我们有一个页面似乎被最新的chrome更新(到84(破坏了。有一个带有onclick事件的复选框,该复选框不再激发。我们收到一个错误:Uncaught TypeError:timeline.toggleWatcher不是函数

附件是调用这个JavaScript函数的HTML

<ul class="dropdown-menu dropdown-menu-right condensed-dropdown">
<li>
<a class="pos-rel" data-watcher-toggle-type="submitter" data-notify="submitter" data-selected="true" onclick="timeline.toggleWatcher('submitter')">
<span class="dropdown-toggle-icon">
<i class="fa fw fa-check-square"></i> 
</span>
<span class="history-filter-label">Submitter</span> </a>
</li>
<li>
<a class="pos-rel" data-watcher-toggle-type="analyst" data-notify="analyst" data-selected="false" onclick="timeline.toggleWatcher('analyst')">
<span class="dropdown-toggle-icon">
<i class="fa fw fa-square-o"></i> 
</span>
<span class="history-filter-label">Assigned Analyst</span></a>
</li>
<li>
<a class="pos-rel" data-watcher-toggle-type="watcher" data-notify="watcher" data-selected="true" onclick="timeline.toggleWatcher('watcher')">
<span class="dropdown-toggle-icon">
<i class="fa fw fa-check-square"></i> 
</span>
<span class="history-filter-label">Watchers</span></a>
</li>
</ul>

timeline是否已成为JavaScript中的保留词?

它不是保留字。此外,如果您使用window.timeline.dosomething,它也会起作用。

您看到此问题的原因是document现在有一个新属性timeline

现在你可能想知道为什么这很重要,你写的不是document.timeline,而是timeline,对吧?好吧,原因是历史性的:为了使编写内联事件处理程序更简单、更短,有些事情在它们的范围内,这在今天有点出乎意料。

详细信息可以在HTML规范中阅读(查看"范围"下的说明(。此外,这个Stack Overflow的答案进一步探讨了这个主题。

您可以想象,您的代码是在多个嵌套的with块中调用的:

  • with (document)
  • 如果处理程序位于<form>:with (formElement)内部的元素上
  • with (element)(为其编写处理程序的元素本身(

本文如下所示:

给定以下标记:

<p onclick="self.alert(event);"></p>

如果用ECMAScript编写扩展的作用域链,它看起来像:

function onclick(event) {
with(document) {
with(this.form) {
with(this) {
self.alert(event);
}
}
}
}

正如您所看到的,问题是在这种情况下,document.timeline在您的作用域中可以作为timeline访问,覆盖具有相同名称的全局变量。

直接的解决方案是使用window.timeline,正如我在上面所写的那样,但今后,建议使用addEventListener,而不是编写内联处理程序。

timeline不是一个"保留字";,它是Document:的一个性质

https://developer.mozilla.org/en-US/docs/Web/API/Document/timeline

您应该以编程方式添加事件处理程序,而不是在标记中使用内联属性并依赖全局变量,因为添加到Document中的任何新属性都会隐藏全局变量。

例如,这很好:

<html>
<head><title>Bug Test</title></head>
<body>
<button id="btn">Works</button>
<script>

var timeline = {
dosomething: function(param){
alert('doing something: '+param);
}
}

document.querySelector('#btn').addEventListener('click', event => {
timeline.dosomething("works");
});
</script>
</body>
</html>

发布后,做了更多的测试。。。现在看来时间线实际上是一个保留词。请参阅下面的示例HTML:

<html>
<head><title>Bug Test</title></head>
<body>
<button onclick="mgtest.dosomething('hello there')">Works</button>
<button onclick="timeline.dosomething('hello there')">Does Not Work</button>
</body>
<script>
var mgtest = {
dosomething: function(param){
alert('doing something: '+param);
}
}
var timeline = {
dosomething: function(param){
alert('doing something: '+param);
}
}
</script>
</html>

相关内容

最新更新