0

I have a following code:

document.body.onload = addElement;

function addElement () {    var myImage = new Image(400, 100); 
myImage.src = 'https://www.google.com/logos/doodles/2017/holidays-2017-day-2-5240850203279360-s.png'; 
myImage.id = "myImageId";   
myImage.onclick = myVerySpecialFunction(); 
document.body.appendChild(myImage);   
var tmp = "myVerySpecialFunctionAnswer()";   
document.getElementById("myImageId").setAttribute("onclick", tmp); } 

function myVerySpecialFunction() {  alert("Knock-knock!"); } 
function myVerySpecialFunctionAnswer() { alert("Who is there!?"); }

When I add to my myImage.onclick function, it fired instantly. Why does it do that? Could I prevent it?
Of course, I can do a workaround here with setAttribute, but I don't like it.
https://jsfiddle.net/kv8w78be/3/

Areso
  • 67
  • 1
  • 2
  • 11
  • 1
    It's because you're calling the function. Use `myImage.onclick = myVerySpecialFunction` <-- no parenthesis. – Mark Dec 24 '17 at 20:56
  • 1
    Because you're immediately calling it instead of giving it a reference of the function. Try `myImage.onclick = myVerySpecialFunction;` instead. – Andy Dec 24 '17 at 20:56
  • @Andy You both are correct. But what if I want to call my function in future with a parameter, how then I should correct describe it? https://jsfiddle.net/kv8w78be/5/ – Areso Dec 24 '17 at 21:07

2 Answers2

2

As Mark and Andy have stated in the comments to your question, it's due to how you are attempting to assign your function to the onClick event.

In JavaScript, there's a difference between calling a function and assignment a function to property. For example,

let myImage = new Image(400, 100);
function foo() { console.log(Hello, world!); }

myImage.onclick = foo(); // As foo() does not return any value, myImage.onclick is set to undefined.
myImage.onclick = foo; // myImage.onclick is set as a reference to function foo().

When you assign foo() to the onClick event, what you are actually saying is 'Assign the value that function foo() returns to myImage.onclick. As such, the function is immediately called.

You instead want to assignment foo, without the parenthesis. This makes myImage.onclick reference the function foo(), making it so the function is called when the onClick event occurs.

Jeffrey
  • 1,271
  • 2
  • 15
  • 31
  • But what if I want to call my function in future with a parameter, how then I should correct describe it? jsfiddle.net/kv8w78be/5 I would like to have a parameter. With parenthesis on setAttribute I could get this behaviour. – Areso Dec 24 '17 at 21:14
  • @Areso That's an entirely different question, but in short, you would want to use `addEventListener()` instead of assigning directly the to event hook. Take a look at [this answer](https://stackoverflow.com/questions/9643311/pass-string-parameter-in-an-onclick-function) for more on that. – Jeffrey Dec 24 '17 at 21:20
  • @Areso, why are you trying to add two functions to that element? You add one to the element with `onclick`, then try and add another one _to the same element_ with `setAttribute`. – Andy Dec 24 '17 at 21:31
  • @Andy I did it with an intention. First time (via object) to show what I try to fix, second time (via setAttribute) to show what I try to achieve. As Jeffrey suggests, I looked to another answer, and what's I want achievable either via setAttribute (and I did it correct), or via addEventListener (I completely was not familiar with that approach in JS). – Areso Dec 26 '17 at 03:23
1

It is fired instantly because the JavaScript interpreter reads myVerySpecialFunction() which is a function call and then attempts to assign the returned value to the onclick event.

The correct way to achieve your desired behaviour would be to assign the function myVerySpecialFunction to your event. and not a function call.

It can be done this way :

document.body.onload = addElement;

function addElement () {    var myImage = new Image(400, 100); 
myImage.src = 'https://www.google.com/logos/doodles/2017/holidays-2017-day-2-5240850203279360-s.png'; 
myImage.id = "myImageId";   
myImage.onclick = myVerySpecialFunction; 
document.body.appendChild(myImage);   
} 

function myVerySpecialFunction() {  alert("Knock-knock!"); } 

Here : https://jsfiddle.net/scubatank115/1gjp8w2o/3/