重命名我的函数后,代码停止工作。这个新名称scrollIntoView
似乎与element.scrollIntoView()
方法冲突。
<div onmousedown="scrollIntoView('id001')"/>
function scrollIntoView(id) {
alert(id);
}
我创建了一个简单的测试用例https://jsfiddle.net/mgtn215y/,表明我的功能甚至被element.scrollIntoView()
忽略了
解决方案很明显-使用不同的函数名称。由于此行为在主要浏览器之间是一致的,因此我希望在某处指定该行为。但是,我找不到任何相关的东西,例如JavaScript lexical grammar。这种行为有背景吗?
答案 0 :(得分:2)
出于某些奇怪的原因,内联处理程序似乎在运行时隐式使用with(this)
,其中this
引用触发事件的元素。每当您尝试引用某物时,如果某物作为this
的属性存在,则该属性将最终被引用,而不是同名的外部变量:
console.log(typeof className); // Undefined in standard global scope
console.log(typeof scrollIntoView); // Undefined in standard global scope
.mydiv {
width: 100px;
height: 100px;
background-color: red;
cursor: pointer;
}
<div class="mydiv" onclick="
console.log(typeof className); // Defined inside inline handler
console.log(typeof scrollIntoView); // Defined inside inline handler
">
对于解释器来说,onclick
实际上 看起来更像:
onclick="with(this) {
console.log(typeof className);
console.log(typeof scrollIntoView);
}"
这很奇怪。但是内联事件处理程序无论如何都是很糟糕的做法,可能不应该使用;使用addEventListener
或onkeydown
正确分配处理程序:
document.querySelector('.mydiv').onmousedown = () => scrollIntoView("id001");
function scrollIntoView(id) {
console.log(id);
}
.mydiv {
width: 100px;
height: 100px;
background-color: red;
cursor: pointer;
}
<div class="mydiv"></div>
答案 1 :(得分:2)
问题是从HTML源中声明的HTML元素属性值编译的函数的作用域链。形式为Pool.map myfiles.output_file
的属性表现出这种行为。
出于历史原因(目前尚不存在DOM,on_eventName=functionBodyCode
尚未出现……),此类函数是使用范围链编译的,该范围链包含提供了事件处理程序属性的对象,该元素所在的任何document.getElementByID
元素以及form
对象。 但是在模拟Netscape行为时,不同的浏览器采用了不同的方法。某些浏览器包含提供事件处理程序属性的元素的所有父对象,而其他浏览器则省略了诸如document
之类的一些相关对象。
技术细节可以在“ Javascript权威指南” O'Reilly的“ 19.1.6。事件处理程序的范围”部分中找到。
主要建议是避免以HTML提供事件处理程序-而是使用document
在JavaScript中添加事件处理程序。如果出于某种原因必须在HTML属性值中编码函数调用,请避免使用作为DOM对象方法的函数名称。
请注意,事件处理程序的自定义范围链仅适用于从HTML属性生成的函数。它不不适用于使用JavaScript创建并使用addEventListener
或addEventListener
添加到元素的函数。
以下代码段演示了在HTML中定义的事件处理程序作用域链中外部元素的属性名称::
element.onEventName=aFunctionObject
在第一种形式中,<form name="formName1" action="">
<p> Try to access the elements collection of the form:
<button type="button"
onclick="console.log( elements);">elements
</button>
</p>
</form>
<form name="formName2" action="" onsubmit="return false">
<p> Try to access form name as form.name:
<button type="button"
onclick="console.log( 'form.name: %s', form.name);">form.name
</button>
</p>
</form>
<form name="formName3" action="" onsubmit="return false">
<p>Access document.write as "write"
<button type="button"
onclick="console.log( 'write: %s', write);">write
</button>
</p>
</form>
是周围表单元素的属性。
在第二种形式中,elements
是HTMLButtonElement的属性。
在第三种形式中,form
是write
的方法。
答案 2 :(得分:0)
要覆盖,只需尝试:
Element.prototype.scrollIntoView = function(id) {
alert(id);
}
但是请注意,它可以与addEventListener
一起使用:
var element = document.getElementById("element");
function scrollIntoView(id) {
alert(id);
}
element.addEventListener("mousedown", function() {
scrollIntoView("id001");
});
div {
width: 100px;
height: 100px;
background-color: red;
cursor: pointer;
}
<div id="element"></div>