1

When the onclick event handler for one element is set directly to the built-in function click of another element the event silently fails to trigger, even though it work when using a user-defined intermediary function.

Similarly, when the onclick event handler is set directly to the built-in function alert it results in a TypeError: Illegal invocation even though it works when using a user-defined intermediary function.

Strangely, when the onclick event handler is set directly to console.log it works as expected, despite this also being a built-in function.

What's going on with click and alert that makes direct assignment behave unexpectedly? Why does the addition of an anonymous function that simply forwards the call make any difference?

const div1 = document.getElementById("1");
const div2 = document.getElementById("2");
const div3 = document.getElementById("3");
const div4 = document.getElementById("4");
const div5 = document.getElementById("5");
const div6 = document.getElementById("6");
const indicator = document.getElementById("indicator");

indicator.onclick = function() {
  if (indicator.style.background == "blue") {
    indicator.style.background = "green";
  } else {
    indicator.style.background = "blue";
  }
};

div1.onclick = function(event) {
  indicator.click(event);
};

div2.onclick = indicator.click;

div3.onclick = function(event) {
  alert(event);
};

div4.onclick = alert;

div5.onclick = function(event) {
  console.log(event);
};

div6.onclick = console.log;
#indicator {
  height: 100px;
  width: 100px;
}
div {
  cursor: pointer;
  text-decoration: underline;
}
<div id="1">Set indicator color via function (works)</div>
<div id="2">Set indicator color directly (silently fails)</div>
<div id="3">Trigger alert via function (works)</div>
<div id="4">Trigger alert directly (fails with error)</div>
<div id="5">Trigger console log via function (works)</div>
<div id="6">Trigger console log directly (works)</div>
<div id="indicator"></div>
Altay_H
  • 489
  • 6
  • 14
  • 3
    I have no clue what you are actually trying to do.... I have a feeling that I am not the only one. – epascarello Mar 18 '19 at 22:05
  • `alert()` is a method. The message parameter can be blank but without the parentheses you do not call the function, but rather a reference to the function. It's explained well on this question: https://stackoverflow.com/questions/35949554/invoking-a-function-without-parentheses – tshimkus Mar 18 '19 at 22:09
  • @epascarello I originally wrote the code `div2.onclick = indicator.click;` to do exactly that: trigger the click of one DOM element when the other is clicked. I was confused by why it wouldn't work without wrapping it in another function, which is why I asked this question. I also tried to do some investigation with other built-in functions (`alert`, `console.log`) which didn't shed any light on the situation. – Altay_H Mar 18 '19 at 22:41

1 Answers1

1

You can not call alert like that because it is no longer executing in the context of the window. It is executing in the context of the div you clicked on. Using bind you can change the context back to the window and it will work.

const div4 = document.getElementById("4");

div4.onclick = alert.bind(window);
#indicator {
  height: 100px;
  width: 100px;
}
div {
  cursor: pointer;
  text-decoration: underline;
}
<div id="4">Trigger alert directly (fails with error)</div>
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • Thanks! I forgot that simply specifying `indicator.click` or `window.alert` doesn't cause it to bind, and that binding would occur in a different context wherever the call actually occurs. – Altay_H Mar 19 '19 at 14:00