LittleBobbyTables
LittleBobbyTables

Reputation: 4473

addEventListener calls the function without me even asking it to

So we have a page:

<span id='container'>
    <a href='#' id='first'>First Link</a>
    <a href='#' id='second'>Second Link</a>
</span>

And want to add some click events:

first.addEventListener('click', function(){alert('sup!');})

Works like a charm! However, when you make the second argument an external function:

function message_me(m_text){
    alert(m_text)
}

second.addEventListener('click', message_me('shazam'))

It calls the function immediately. How can I stop this? So annoying!

Here's a live demo: http://jsfiddle.net/ey7pB/1/

Upvotes: 56

Views: 66522

Answers (6)

Mehrdad995
Mehrdad995

Reputation: 47

You can just use the function name to reference it and pass the required inputs as options like below:

second.addEventListener('click', message_me, 'shazam');

remember that in JS having () after the function name automatically calls the function and use the returned value.

Upvotes: 0

Maik Lowrey
Maik Lowrey

Reputation: 17566

Year 2022

I know the following possibilities:

option 1 (anonymous function)

function message_me(m_text){
    alert(m_text);
}

second.addEventListener('click', function () {
    message_me('shazam')
});

option 2 (callback fn calls a annoymous fn)

function message_me(m_text){
    return function () {
        alert(m_text);
    };
}

second.addEventListener('click', message_me('shazam'));

option 3 (bind())

function message_me(m_text){
    alert(m_text);
}

second.addEventListener('click', message_me.bind(this,'shazam'));

option 4 (arrow fn)

function message_me(m_text){
    alert(m_text);
}

second.addEventListener('click', () => {
    message_me('shazam')
});

I personally like to use the (option 4) arrow function because you get the context included. Another nice solution is the bind (option 3). What bothers me a bit about this variant is that you have to explicitly include the context with this. That can easily be forgotten. Option 1 is fine and this may have been the standard way in the past. To option 2 I can only say: it works but for my taste it looks awkward.

But basically you have to take what you find most understandable from the syntax. Because in the end you have to remember so much, then make your life easier and take what you can remember best. In my case that is option 4 and option 3 then option 1 and option 2 is not an alternative for me.

Upvotes: 3

clav
clav

Reputation: 4251

Quoting Ian's answer:

Since the second parameter expects a function reference, you need to provide one. With your problematic code, you're immediately calling the function and passing its result (which is undefined...because all the function does is alert and doesn't return anything). Either call the function in an anonymous function (like your first example) or alter the function to return a function.

function message_me(m_text){
    alert(m_text)
} 

second.addEventListener('click', 
    function() {
        message_me('shazam');
    }
);

Here's an updated fiddle.

Upvotes: 47

Jesse Reza Khorasanee
Jesse Reza Khorasanee

Reputation: 3471

Modern ES6 solution using arrow functions

second.addEventListener('click', () => message_me('shazam'))

Upvotes: 19

avseoul
avseoul

Reputation: 256

or you can use .bind

function message_me(m_text){
    alert(m_text);
}

second.addEventListener('click', message_me.bind(this, 'shazam'));

check MDN Documentation about 'closures'

Upvotes: 22

Ian
Ian

Reputation: 50905

Since the second parameter expects a function reference, you need to provide one. With your problematic code, you're immediately calling the function and passing its result (which is undefined...because all the function does is alert and doesn't return anything). Either call the function in an anonymous function (like your first example) or alter the function to return a function.

You can do this:

function message_me(m_text){
    alert(m_text);
}

second.addEventListener('click', function () {
    message_me('shazam')
});

or this:

function message_me(m_text){
    return function () {
        alert(m_text);
    };
}

second.addEventListener('click', message_me('shazam'));

DEMO: http://jsfiddle.net/tcCvw/

Upvotes: 28

Related Questions