How to pass parameters in function calls by reference in Javascript?

Asked

Viewed 48,548 times

39

8 answers

22


It was thinking about this situation that was added between the parameters of .on the possibility to pass arbitrary data to the Handler. Any object passed as a parameter just before the Handler will be available within it through event.data. Example:

function retornaNada(evento) {
    var data = evento.data;
    console.log(data.foo); // Imprime "bar"
}

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

Several other jQuery methods accept this parameter data. In the case of "on", the general form (according to the documentation) is:

.on( events [, selector ] [, data ], Handler(eventObject) )

If this is not enough for you (e.g., you already have a function ready, and want to use it without modification as Handler event), then it is necessary to transform it through the operation of currying. There are several ways to do this:

  1. currying "manual":

    $("a").on("click", function(e) { retornaNada(10); });
    
  2. jQuery.proxy:

    $("a").on("click", jQuery.proxy(retornaNada, meuThis, 10));
    
  3. Function that returns function:

    function tranforma(parametro) {
        return function(evento) {
            retornaNada(parametro);
        }
    }
    
    $("a").on("click", transforma(10));
    

    or more generic:

    function tranforma(fn, meuThis, parametro) {
        return function(evento) {
            fn.call(meuThis, parametro);
        }
    }
    
    $("a").on("click", transforma(retornaNada, meuThis, 10));
    

    or even more generic (reaching a point that is almost identical to the jQuery.proxy):

    function tranforma(fn, meuThis) {
        var args = Array.prototype.slice.call(arguments, 2, arguments.length);
        return function(evento) {
            fn.apply(meuThis, args);
        }
    }
    
    $("a").on("click", transforma(retornaNada, meuThis, 10));
    

Update: on the use of this

Both in the case of jQuery.proxy how much in my job transforma (in the most generic forms), a parameter meuThis is expected. This is because every function invocation in Javascript expects a Binding for the keyword this, even when the function is not being called in the content of an object (i.e. it is not a method). Example:

console.log(this); // Vai imprimir o "objeto global" (no caso de um browser, "window")

function a() {
    console.log(this);
}
a(); // também imprime o objeto global

var obj = { x:a };
obj.x(); // Vai imprimir "obj"

obj.criaLinks = function() {
    $("a").on("click", jQuery.proxy(retornaNada, this, 10));
    // Como se fosse: obj.retornaNada(10)

    $("a").on("click", jQuery.proxy(retornaNada, window, 10));
    // Como se fosse: window.retornaNada(10)

    $("a").on("click", jQuery.proxy(retornaNada, { foo:"bar" }, 10));
    // Como se fosse: { foo:"bar" }.retornaNada(10)
};
obj.criaLinks();
  • Your first way to use would be using anonymous function, right? And what would be this variable meuThis and what use in the proxy method?

  • @Philippegioseffi In Javascript, every function has a this. If you do not specify one, use the global object (in the case of a browser, window) as this. In the case of jQuery.proxy, the specification of a this is mandatory, so you have to pass something on to her (even if you don’t use it). If you don’t have a this to pass, use window, then she’d look the same as if you hadn’t used any...

  • In the case of a browser? What would be another case? And pass this or window are equivalent, certain?

  • @Philippegioseffi If you are running Javascript on the server side (eg.: Node.js, Rhino, etc) then there is no browser, and consequently there is no browser window. The "global object" in this case would be another. And as to pass this or window makes a difference yes: in one case you are using the same this of the function calling the proxy, on the other you’re using window and point. I will update the answer with an example, to be clearer.

  • Ah, I’ve heard of Server Side Javascript, but unfortunately I’ve never seen in use nor examples on the Internet (I confess I haven’t searched much either).

  • @Philippegioseffi I updated the answer with a very simplified explanation. If you have more questions about the overall object or how this works, I suggest opening another question :)

  • Excellent response with this latest update, thank you very much for the contextualization!

Show 2 more comments

5

What you can use here is the jQuery.proxy():

$('div').on('click', $.proxy( minhaFuncao, this, 'minha variavel1', 'minha variavel2' ));

function minhaFuncao(a, b) {
    console.log(a, b);
}

Example

So you can pass parameters into the function, keeping the reference to the function.

This method allows passing the referenced function, allows changing the scope of the this and allows you to pass more arguments into the function.

  • But isn’t it easier to use Anonymous Function? Unless this function is used in more than one place of course.

  • 1

    @Philippegioseffi, depends: the anonymous function cannot be referenced. In this case I would say yes. I answered to show an alternative. In some cases this method is more useful. In this case, as you said, it may be better with the anonymous function.

  • You could explain better what it would be change the scope of this?

  • @Philippegioseffi, if you have an anonymous function, jQuery stops as this the element where it applies the "Event Handler", using with the proxy, can change this to the window, or very practical for a Class. This technique is widely used.

  • In this example you gave the this would be the div then, correct? And what would be Class?

  • @Philippegioseffi, not the div would be the window. Class is a javascript class, an object {}

  • But in your answer you said that jQuery passes as this the element where it applies the "Event Handler" and you’re applying the event in a div, right? I understood what class is, I didn’t know that objects could be called class also in JS.

Show 2 more comments

4

There is no reference passage in Javascript, but you can encapsulate this in an object (which is always passed by reference, since only the object pointer is passed in reality).

Ex.:

function teste(argumento)
{
    argumento.valor = 10;
}

var o = { valor = 11 };

teste(o);
o.valor == 10; // true

As there is only one object in memory, the changes in memory are global.

  • 1

    But what I would call your function teste(argumento) within an on method? $("a").on("click", teste), but where your parameter enters here?

2

Your previous question answers that:

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

I have a question, some jQuery methods expect a function like parameter, but to work they must receive an Inner Function as parameter instead of a function directly, as in the example below:

$("a"). on("click", Function() { returnNada(); }); instead of

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

  • 1

    But my doubt now is how to pass parameters on a function we call reference, ie without using an anonymous function. And in your example you do not pass parameters in the function retornaNada().

  • The code pasted here is your previous question. In my opinion the best practice is to use the call with the anonymous method.

  • Calling with anonymous method is the most widespread way, but you know how it would be without anonymous method?

  • You have marked the satisfactory answer for your case. That option works for some jQuery methods only, not for javascript. I see no difficulty in calling with an anonymous method, in my reply I commented that your previous question, which asked why one option was used instead of another, the most coherent answer would be this your question now: We use anonymous function calls to another, just to pass parameters. Sorry I was unclear in the reply.

  • Oh yes, now I understand what you mean, I may not have been clear in my question here. In this question I wanted to know how to pass parameters without using anonymous function, just to know more the same syntax, anyway your answer aggregates and I voted in it too.

  • Perfect. I thought it was nice that you linked the two questions, because they complement each other...

Show 1 more comment

2

From what I understand you want to pass parameters to the function retornaNada as it passes it as jQuery function parameter on...

As far as I know there is no way to do this within good practice, but you could create a function that receives another as parameter and return a new function with the actual call within the scope.

Something like that:

Function.prototype.getFunction = function (context) {
    var
        args = arguments,
        foo = this;
    return function () {
        foo.apply((context || window), Array.prototype.slice.call(args, 1));
    };
};

Then your call would look like this:

$("a").on("click", retornaNada.getFunction(this, arg1, arg2));
  • It is a way of doing it, but much more complex than those presented by the other answers.

2

The way you’re doing, that’s using a Closure(as I told you in the previous question) you are passing a reference from a function to the argument, which is expected.

However, you can use parameters if you return a function in the return of the function you called.

For example:

function retornaFunction(data){
  return function(){console.log("Data: "+data+" This: "+this)};
}
var data = 1;
$('div').on("click", retornaFunction(data));

See that you are passing the parameter data and can also access the context this which refers to your clicked element, of which is widely used in functions assignments like this that you are proposing.

In fact, there are other ways to do what you want, not by using the function .on().

For example:

function retornaFunction(data){
      return function(){console.log("Data: "+data+" This: "+this)};
    }
    var data = 1;
$('div').click(retornaFunction(data));

This way you do not need to pass "click" as parameter.

You can also create an element and assign an event to Click for him in his creation as for example:

function retornaFunction(data){
  return function(){console.log("Foo: "+data+this)};
}
data = 1;
var $div = $('<div />', {
  "class": "suaclasse", //opcional apenas exemplo
  text: "texto qualquer"//opcional apenas exemplo
}).click(retornaFunction(data)); //aqui você atribui o clique.

$('body').append($div);//joga a div no body de seu documento
  • Actually from what I read in the documentation when using the methods click, change and etc. you use on implicitly.

  • 1

    Technically yes, but I’m used to using .click, .change etc. The difference in performance should be almost non-existent, and is more practical.

1

You can pass several parameters via javascript using this example:

function abreJanela(URL,URL2) {
location.href = "#?pg=pecas&nome="+URL+"&ano_base="+URL2;  
  
  
  //este metoo manda parametros via GET
  alert("#?pg=pecas&nome="+URL+"&ano_base="+URL2+"");
};
<select    name="ano"  id="ano"   class="select" >	
							<option     value="2014">2014</option>
							<option     value="2015" selected>2015</option>
							</select>
Nome:<input   onchange="javascript: abreJanela(this.value, ano.value)"   type="text"  name="corrida"   >

<br>

Basta completar campo e clicar ENTER

-1

elementoid.on("input", $.proxy(func_atualizadigitando, this, elementoid) );

function func_atualizadigitando(tag){
    var conteudo = tag.val();
    var qtdpalavras = conteudo.split(/\S+/).length-1;
    $("#cont-palavras").text(qtdpalavras);

    var qtdcarac = conteudo.length;
    $("#cont-carac").text(qtdcarac);
}
  • Please add an explanation about the relevant parts of the code so you can understand how this solves the issue.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.