JavaScript 中的保留函数名称
Reserved function names in JavaScript
重命名我的函数后,代码停止工作。新名称 scrollIntoView
似乎与 element.scrollIntoView()
方法冲突。
<div onmousedown="scrollIntoView('id001')"/>
function scrollIntoView(id) {
alert(id);
}
我创建了一个简单的测试用例 https://jsfiddle.net/mgtn215y/,它表明我的函数被忽略了 element.scrollIntoView()
甚至
- 它没有在元素上调用
- 属性不匹配
解决方案很明显 - 使用不同的函数名称。由于这种行为在主要浏览器中是一致的,我希望这在某处指定。但是,我找不到任何相关内容,例如JavaScript lexical grammar。这种行为有什么背景吗?
要覆盖,只需尝试:
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>
出于某些奇怪的原因,内联处理程序在 运行 时似乎隐式使用 with(this)
,其中 this
引用触发事件的元素。每当您尝试引用某些内容时,如果该内容作为 this
的 属性 存在,那么 that 属性 将最终被引用,而不是具有相同名称的外部变量:
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>
问题是从 HTML 源中声明的 HTML 元素属性值编译的函数范围链。 on_eventName=functionBodyCode
形式的属性表现出这种行为。
由于历史原因(DOM 的当前形式不存在,document.getElementByID
还没有被发明......)这些函数是用一个作用域链编译的,该作用域链包含对象提供了事件处理程序属性、元素所在的任何 form
元素以及 document
对象。 但是 不同的浏览器在模拟 Netscape 行为时采用了不同的方法。一些浏览器包含了提供事件处理程序属性的元素的所有父对象,而其他浏览器则省略了一些相关对象,例如 document
.
技术细节可以在“Javascript 权威指南”O'Reilly,“19.1.6. 事件处理程序的范围”一节中找到。
主要建议是避免在 HTML 中提供事件处理程序 - 使用 addEventListener
将它们添加到 JavaScript 中。如果出于某种原因必须在 HTML 属性值中对函数调用进行编码,请避免使用作为 DOM 对象方法的函数名称。
请注意,事件处理程序的自定义作用域链仅适用于从 HTML 属性生成的函数。它 不 适用于在 JavaScript 中创建并使用 addEventListener
或 element.onEventName=aFunctionObject
.
添加到元素的函数
以下代码片段演示了在 HTML 中定义的事件处理程序范围链中定位 属性 外部元素的名称::
<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
是周围形式元素的属性。
在第二种形式中,form
是 HTMLButtonElement 的 属性。
在第三种形式中,write
是document
的一个方法。
引用 2020 年,HTML5 将 HTML 属性处理程序的范围链指定为“Scope 下的“元素 > 外部形式元素 > 文档” " internal raw uncompiled handler 的编号列表项 3.9 中。
重命名我的函数后,代码停止工作。新名称 scrollIntoView
似乎与 element.scrollIntoView()
方法冲突。
<div onmousedown="scrollIntoView('id001')"/>
function scrollIntoView(id) {
alert(id);
}
我创建了一个简单的测试用例 https://jsfiddle.net/mgtn215y/,它表明我的函数被忽略了 element.scrollIntoView()
甚至
- 它没有在元素上调用
- 属性不匹配
解决方案很明显 - 使用不同的函数名称。由于这种行为在主要浏览器中是一致的,我希望这在某处指定。但是,我找不到任何相关内容,例如JavaScript lexical grammar。这种行为有什么背景吗?
要覆盖,只需尝试:
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>
出于某些奇怪的原因,内联处理程序在 运行 时似乎隐式使用 with(this)
,其中 this
引用触发事件的元素。每当您尝试引用某些内容时,如果该内容作为 this
的 属性 存在,那么 that 属性 将最终被引用,而不是具有相同名称的外部变量:
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>
问题是从 HTML 源中声明的 HTML 元素属性值编译的函数范围链。 on_eventName=functionBodyCode
形式的属性表现出这种行为。
由于历史原因(DOM 的当前形式不存在,document.getElementByID
还没有被发明......)这些函数是用一个作用域链编译的,该作用域链包含对象提供了事件处理程序属性、元素所在的任何 form
元素以及 document
对象。 但是 不同的浏览器在模拟 Netscape 行为时采用了不同的方法。一些浏览器包含了提供事件处理程序属性的元素的所有父对象,而其他浏览器则省略了一些相关对象,例如 document
.
技术细节可以在“Javascript 权威指南”O'Reilly,“19.1.6. 事件处理程序的范围”一节中找到。
主要建议是避免在 HTML 中提供事件处理程序 - 使用 addEventListener
将它们添加到 JavaScript 中。如果出于某种原因必须在 HTML 属性值中对函数调用进行编码,请避免使用作为 DOM 对象方法的函数名称。
请注意,事件处理程序的自定义作用域链仅适用于从 HTML 属性生成的函数。它 不 适用于在 JavaScript 中创建并使用 addEventListener
或 element.onEventName=aFunctionObject
.
以下代码片段演示了在 HTML 中定义的事件处理程序范围链中定位 属性 外部元素的名称::
<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
是周围形式元素的属性。在第二种形式中,
form
是 HTMLButtonElement 的 属性。在第三种形式中,
write
是document
的一个方法。引用 2020 年,HTML5 将 HTML 属性处理程序的范围链指定为“Scope 下的“元素 > 外部形式元素 > 文档” " internal raw uncompiled handler 的编号列表项 3.9 中。