Uncaught TypeError: lang is not a function [duplicate]

Consider this code:

<input type="button" value="Debugger Test" onclick="debugger;" />
<input type="button" value="Prototype Test" onclick="console.log(__proto__);" />

When you click on “Debugger Test” and open your debugger, you’ll see that there seems to be an implicit with scope wrapped around the onclick, making all the <input>’s properties accessible without needing to refer to the button.

Clicking on “Prototype Test” logs the prototype of the current scope. You’ll see that it’s the HTMLInputElement’s prototype, making all the scopable properties of this entire prototype chain available to the scope.

Interestingly, the scopable part of the prototype chain of the current HTMLDocument is included as well.

All this means that all global attributes (lang is one of them) and several others specific to buttons are overridden. E.g. value, type also wouldn’t work. Similarly, variables like createElement (from document) also wouldn’t work, but the unscopable append (from ParentNode.prototype) would.

All this is also explained in this answer to a related question about global variables clashing with window properties.


Your best bet is to use the standard way of adding event listeners: addEventListener.

<input type="button" value="Test" />
<script>
  function lang() {
    alert("Hello, World! It’s not an HTML event handler attribute this time");
  }

  document.querySelector("input").addEventListener("click", lang);
</script>

Leave a Comment