1

I have recently asked the question, Why should we use anonymous functions with jQuery instead of the function directly? and along with the accepted answer came a second question: How to pass arguments to one JS function that we are invoking by reference?

How would be the call to $("a").on("click", retornaNada); whether this function receives a simple parameters such as a number or as a more complex object?

3
  • 1
    the arguments passed to retornaNada are set by $.on(), so it will be the same pattern each invocation. you can define extra params and curry the first ones using Function.bind(). Commented Feb 3, 2014 at 18:19
  • Could you post an example? Commented Feb 3, 2014 at 18:21
  • It is now, thanks for remembering, @Jack. Commented Feb 3, 2014 at 18:27

4 Answers 4

5

To your actual example:

$("a").on("click", retornaNada); 

If you read the jQuery docs, it will tell you what it will pass to the handler. It will call whatever function you provide and pass it an eventObject which has various properties (see the docs). If you want, you can pass more data as part of your binding that will end up in event.data (see the section Passing data to the handler)

So if you do:

$("a").on("click", { foo:"bar" }, retornaNada);

and have a function retornaNada:

function retornaNada(e) {
    console.log(e.data.foo);     // logs "bar"
}

Alternatively, if you want more control over what gets passed to your function, this would be a good place to use those anonymous functions:

$("a").on("click", function() { 
    retornaNada(myOwn, argumentsTo, myFunction); 
});

So, for example, if retornaNada looked like this:

function retornaNada(anumber) {

}

You could then do:

$("a").on("click", function() { 
    retornaNada(1); 
});

Edit: Some thoughts on the first option (using data) and the second (wrapping with an anonymous function).

Let's say you have a function called addToTotal that is going to increase a counter every time an event happened. With the first option, your function might look like this:

function addToTotal(e) {
    theTotal += e.data.amountToAdd;
}

This is fine, of course, but what if you also have other logic elsewhere that you need to increase your total? You need to either reproduce the logic of the body of your function (either inline or in another function), or you need to "fake" and event object

addToTotal({ data: 1 });     // fake event object - this is kind of stupid

In addition, a function addToTotal that takes an argument that isn't actually the amount you want to add is goofy and will likely confuse anybody else looking at your code.

In that case, it would be a lot better to define addToTotal more sensibly to take a number and add it to the total:

function addToTotal(number) {
    theTotal += number;
}

Now I can call it anywhere:

addToTotal(1);     // this looks a lot better!

but I can't use it as an event handler because it will pass an eventObject instead of the number I need so this:

$("a").on("click", addToTotal)

Isn't going to work. So instead, we can wrap our function in an annoymous function:

$("a").on("click", function() { addToTotal(1); } )

And now we have an event that will call our function, and our function doesn't look goofy and can be completely agnostic about whether it's called from an event handler or called somewhere else.

Of course, if you really wanted to, you could do this:

function addToTotalEventHandler(e) {
    addToTotal(e.data.amountToAdd);
}

And then:

$("a").on("click", { data : 1 }, addToTotalEventHandler);

But that is basically the same as the anonymous wrapper, but you've had to create a new function just for this single use.

Sign up to request clarification or add additional context in comments.

5 Comments

I didn't understand the alternative, could explain more? And what are those myOwn, argumentsTo, myFunction parameters?
@Philippe: They are whatever you want them to be. What arguments does your function retornaNada actually take? I edited a little to (hopefully) make that clearer.
OK, now I get it, this way is how almost everybody does, i wanted to know only for knowing the syntax purpose how we do it without a anonymous function and you showed in the first example. I just dind't got why we have more control in the second alternative than in the first.
@Philippe: In the first example, your function must be expecting an eventObject as an argument. This is fine, if handling events is all this function is going to do, but can be a problem if you want you function to be called from other places. The second option, where you wrap your function in an anonymous function, allows you to have retornaNada take whatever arguments you want without worrying about how it was called.
Thanks for the explanations, yours is my accepted answer.
3

When you use $("a").on("click", retornaNada) the given function is called like:

retornaNada.call(<anchor-object>, <event-data>)

Whereby <anchor-object> is the DOM object of the anchor that's clicked, available to your function as this, and <event-data> is a wrapper object for the click event itself, so:

function retornaNada(e)
{
    console.log(this); // DOM object
    console.log(e); // event object
}

If your function does not expect an event object as its first argument, the typical thing to do is use a wrapper function, i.e.:

$('a').on('click', function(e) {
    retornaNada(... whatever ...);
});

2 Comments

But what if retornaNada() has now parameters and becomes retornaNada(number)?
If your function does not expect an event object as its first parameter you need a wrapper function.
1

Here is an example:

var foo = function () {
  console.log(arguments);
};

We can invoke it as:

foo(1,2,3,4);                  //[1,2,3,4]
foo.apply(window, [1,2,3,4]);  //[1,2,3,4]
foo.call(window, 1,2,3,4);     //[1,2,3,4]

We can pass foo to another function and invoke it the same way:

function bar() {
  foo(1,2,3,4);                  //[1,2,3,4]
  foo.apply(window, [1,2,3,4]);  //[1,2,3,4]
  foo.call(window, 1,2,3,4);     //[1,2,3,4]
}

7 Comments

Wouldn't be var foo = function(arguments) { console.log(arguments); };, otherwise how would console.log know what is arguments?
Each function has variable called arguments inside its body. @Philippe checkout developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
"arguments" is predefined inside all JS functions.
One more information that I didn't know. Great answer!
|
1

You can use the Function Prototype Bind.

Basicly, it rebind the arguments of the function reference. But you lose the reference to this (which is the same of event.currentTarget).

You would use it like this :

$("a").on("click", retornaNada.bind('something that will equal this', 'arg1', 1));

And the function receive :

function retornaNada(a, b, c){
    console.log(this); //'something that will equal this'
    console.log(a); //'arg1'
    console.log(b); // 1
    console.log(c); // Event object
}

Using bind, the first passed argument will be the this reference and following argument will be arguments in function.

The original arguments (in this case Event) will always be the last one.

3 Comments

So in your example this would be a and the argument passed as 1 has no purpose at all, right?
@Philippe those are random values. In this case, this is a string containing something that will equal this (the first argument when calling .bind()) and a is a string arg1 since it is the second argument in bind. But no argument have a purpose in this example...
Sorry, I didn't understand in my first reading, now I get it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.