Reputation: 5573
I noticed this odd behavior while writing some demonstration code today, and I'm curious what's happening. "Button" does not work although "Button 2" does, even though they're being set in just different ways. I know it has to do with the quoting, but I'm curious why this is happening. Similarly, if I pass in a function to button 3 in quotes vs appending it directly in button 4, button 4 works but button 3 doesn't.
Also, I would think that given that button 2 works, it would do the evaluation of console.log("test")
immediately (similar to how it would work without the quotes) but rather it delays until actually clicking on the button. I know this is not the best way to do it but for curiosity sake, I'm curious what's happening exactly here.
document.getElementById("app").innerHTML = `
<h1>Testing Sandbox</h1>
<div>
<button id='hello'>Button</button>
<button id='hello2' onclick='console.log("test")'>Button 2</button>
<button id='hello3' onclick='(e) => console.log("test")'>Button 3</button>
<button id='hello4'>Button 4</button>
</div>
`;
document.getElementById("hello").onclick = 'console.log("test")';
document.getElementById("hello4").onclick = (e) => console.log("test");
<!DOCTYPE html>
<html>
<head>
<title>Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app"></div>
<script src="src/index.js">
</script>
</body>
</html>
Upvotes: 1
Views: 61
Reputation: 37755
Why button two works ?
It is possible to associate an action with a certain number of events that occur when a user interacts with a user agent. Each of the "intrinsic events" listed above takes a value that is a script. The script is executed whenever the event occurs for that element. The syntax of script data depends on the scripting language.
HTML Specs
So onclick = script [CT]
will be called whenever user interacts, in this case it is an mouse click event
Why button don't work ?
document.getElementById("hello").onclick
expects a function where as you're passing string
Upvotes: 0
Reputation: 371019
When you assign to onclick
, you invoke a setter, which does something pretty similar to calling addEventListener
with the assigned expression. But both addEventListener
and onclick
will silently fail if the passed expression is not a function:
document.getElementById("app").innerHTML = `
<h1>Testing Sandbox</h1>
<div>
<button id='hello'>Button</button>
`;
document.getElementById("hello").onclick = 'console.log("test")';
// nearly the same thing as:
document.getElementById("hello").addEventListener('click', 'console.log("test")');
<div id="app"></div>
The string does not get implicitly coerced to a function.
In the third example, the inline handler declares a function, but never executes it:
<button id='hello3' onclick='(e) => console.log("test")'>Button 3</button>
which is like
button.addEventListener('click', function(event) {
(e) => console.log("test")
});
The listener runs, but the listener doesn't contain anything other than an unused function expression, so you don't see anything when you click. This might be clearer if you add a log statement:
<button id='hello3' onclick='console.log("listener running;"); (e) => console.log("test")'>Button 3</button>
In general, you should never use inline handlers; they require global pollution, are hard to manage, have string and HTML escaping issues, and are pretty much universally considered to be bad practice. Instead, use addEventListener
, and always pass it functions, not strings, for a listener to be properly added.
Upvotes: 4