Reserved function names in JavaScript

落花浮王杯 提交于 2019-12-02 01:23:52

The issue is the scope chain of functions compiled from HTML element attribute values declared in HTML source. Attributes of the form on_eventName=functionBodyCode exhibit this behavior.

For historical reasons (the DOM did not exist in its current form, document.getElementByID had yet to be invented...) such functions are compiled with a scope chain comprising the object on which the event handler attribute is provided, any form element the element is within, and the document object. However different browsers took different approaches when emulating Netscape behavior. Some browsers included any and every parent object of an element providing an event handler attribute, while others omitted some pertinent objects such as document.

Technical detail may be found in "Javascript the definitive guide" O'Reilly, section "19.1.6. Scope of Event Handlers".

The main recommendation is to avoid supplying event handlers in HTML - add them in JavaScript using addEventListener instead. If for some reason function calls must be coded in HTML attribute values, avoid using function names that are methods of DOM objects.

Note the custom scope chain for event handlers only applies to functions generated from HTML attributes. It does not apply to functions created in JavaScript and added to an element using addEventListener or element.onEventName=aFunctionObject.


The following snippet demonstrates locating property names of outer elements in the scope chain of event handlers defined in 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>
  • In the first form, elements is a property of the surrounding form element.

  • In the second form, form is a property of the HTMLButtonElement.

  • In the third form, write is a method of document.

For some strange reason, it looks like inline handlers implicitly use with(this) when they run, where this references the element that triggered the event. Whenever you try to reference something, if that something exists as a property of this, then that property will end up being referenced, rather than an outer variable with the same name:

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
">

To the interpreter, the onclick actually looks something more like:

onclick="with(this) {
  console.log(typeof className);
  console.log(typeof scrollIntoView);
}"

It's pretty strange. But inline event handlers are terrible practice anyway, and probably shouldn't be used; assign the handler properly with addEventListener or onkeydown instead:

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>

To override, simply try:

Element.prototype.scrollIntoView = function(id) {
    alert(id);
}

But do note that it works with 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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!