Pasar una función JavaScript como parámetro


¿Cómo paso una función como parámetro sin que la función se ejecute en la función "padre" o usando eval()? (Ya que he leído que es inseguro.)

Tengo esto:

addContact(entityId, refreshContactList());

Funciona, pero el problema es que refreshContactList se activa cuando se llama a la función, en lugar de cuando se usa en la función.

Podría sortearlo usando eval(), pero no es la mejor práctica, según lo que he leído. ¿Cómo puedo pasar una función como parámetro en JavaScript?

Author: Nic Hartley, 2012-11-08

13 answers

Solo necesita eliminar el paréntesis:

addContact(entityId, refreshContactList);

Esto entonces pasa la función sin ejecutarla primero.

Aquí hay un ejemplo:

function addContact(id, refreshCallback) {
    refreshCallback();
    // You can also pass arguments if you need to
    // refreshCallback(id);
}

function refreshContactList() {
    alert('Hello World');
}

addContact(1, refreshContactList);
 740
Author: user75525,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-08 09:43:33

Si desea pasar una función, simplemente haga referencia a ella por nombre sin los paréntesis:

function foo(x) {
    alert(x);
}
function bar(func) {
    func("Hello World!");
}

//alerts "Hello World!"
bar(foo);

Pero a veces es posible que desee pasar una función con argumentos incluidos, pero no hacer que se llame hasta que se invoque la devolución de llamada. Para hacer esto, cuando lo llame, simplemente envuélvalo en una función anónima, como esta:

function foo(x) {
   alert(x);
}
function bar(func) {
   func();
}

//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });

Si lo prefiere, también podría usar la función apply y tener un tercer parámetro que es una matriz de los argumentos, como:

function eat(food1, food2)
{
    alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args)
{
    //do stuff
    //...
    //execute callback when finished
    callback.apply(this, args);
}

//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]); 
 231
Author: dallin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-07 01:23:03

Ejemplo 1:

funct("z", function (x) { return x; });

function funct(a, foo){
    foo(a) // this will return a
}

Ejemplo 2:

function foodemo(value){
    return 'hello '+value;
}

function funct(a, foo){
    alert(foo(a));
}

//call funct    
funct('world!',foodemo); //=> 'hello world!'

Mira esto

 40
Author: Gadde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:49

Para pasar la función como parámetro, simplemente elimine los corchetes!

function ToBeCalled(){
  alert("I was called");
}

function iNeedParameter( paramFunc) {
   //it is a good idea to check if the parameter is actually not null
   //and that it is a function
   if (paramFunc && (typeof paramFunc == "function")) {
      paramFunc();   
   }
}

//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled); 

La idea detrás de esto es que una función es bastante similar a una variable. En lugar de escribir

function ToBeCalled() { /* something */ }

También podrías escribir

var ToBeCalledVariable = function () { /* something */ }

Hay diferencias menores entre los dos, pero de todos modos - ambos son formas válidas de definir una función. Ahora, si defines una función y la asignas explícitamente a una variable, parece bastante lógico, que puedas pasarla como parámetro a otra función, y no necesitas corchetes:

anotherFunction(ToBeCalledVariable);
 30
Author: naivists,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-18 23:44:51

Hay una frase entre los programadores de JavaScript:" Eval es malo " así que trate de evitarlo a toda costa!

Además de la respuesta de Steve Fenton, también puede pasar funciones directamente.

function addContact(entity, refreshFn) {
    refreshFn();
}

function callAddContact() {
    addContact("entity", function() { DoThis(); });
}
 15
Author: series0ne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-08 09:39:35

También puedes usar eval() para hacer lo mismo.

//A function to call
function needToBeCalled(p1, p2)
{
    alert(p1+"="+p2);
}

//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
    eval(aFunction + "("+params+")");
}

//A function Call
callAnotherFunction("needToBeCalled", "10,20");

Eso es todo. También estaba buscando esta solución y probé soluciones proporcionadas en otras respuestas, pero finalmente conseguí trabajar con el ejemplo anterior.

 5
Author: NullPointer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-23 11:29:16

Sugiero poner los parámetros en una matriz, y luego dividirlos usando la función .apply(). Así que ahora podemos pasar fácilmente una función con muchos parámetros y ejecutarla de una manera simple.

function addContact(parameters, refreshCallback) {
    refreshCallback.apply(this, parameters);
}

function refreshContactList(int, int, string) {
    alert(int + int);
    console.log(string);
}

addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
 5
Author: Naramsim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-26 17:44:14

Me corté todo el pelo con ese tema. No pude hacer que los ejemplos anteriores funcionaran, así que terminé como :

function foo(blabla){
    var func = new Function(blabla);
    func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");

Y eso funciona a las mil maravillas ... por lo que necesitaba al menos. Espero que ayude a algunos.

 4
Author: Fenix Aoras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-15 09:31:35

Aquí hay otro enfoque:

function a(first,second)    
{        
return (second)(first);           
}     

a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world     
 2
Author: cochon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-15 16:21:22

De hecho, parece un poco complicado, no lo es.

Método Get como parámetro:

 function JS_method(_callBack) { 

           _callBack("called");  

        }

Puede dar como un método de parámetro:

    JS_method(function (d) {
           //Finally this will work.
           alert(d)
    });
 2
Author: Hakkı Eser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-21 07:42:53

Las otras respuestas hacen un excelente trabajo describiendo lo que está pasando, pero un "gotcha" importante es asegurarse de que todo lo que pase sea de hecho una referencia a una función.

Por ejemplo, si pasa a través de una cadena en lugar de una función, obtendrá un error:

function function1(my_function_parameter){
    my_function_parameter();   
}

function function2(){
 alert('Hello world');   
}

function1(function2); //This will work

function1("function2"); //This breaks!

Ver JsFiddle

 2
Author: Victor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-23 20:54:26

En algún momento en el que necesite tratar con el controlador de eventos , por lo que necesita pasar event también como argumento, la mayoría de las bibliotecas modernas como react, angular podría necesitar esto.

Necesito anular la función Onubmit (función de biblioteca de terceros) con alguna validación personalizada en reactjs y pasé la función y el evento como se muestra a continuación

ORIGINALMENTE

    <button className="img-submit" type="button"  onClick=
 {onSubmit}>Upload Image</button>

HIZO UNA NUEVA FUNCIÓN upload y llamó passed onSubmit y event como argumentos

<button className="img-submit" type="button"  onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>

upload(event,fn){
  //custom codes are done here
  fn(event);
}
 0
Author: sumit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-20 23:56:09

También puede usar un JSON para almacenar y enviar funciones JS.

Compruebe lo siguiente:

var myJSON = 
{
    "myFunc1" : function (){
        alert("a");
    }, 
    "myFunc2" : function (functionParameter){
        functionParameter();
    }
}



function main(){
    myJSON.myFunc2(myJSON.myFunc1);
}

Esto imprimirá 'a'.

Lo siguiente tiene el mismo efecto con lo anterior:

var myFunc1 = function (){
    alert('a');
}

var myFunc2 = function (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Que también tiene el mismo efecto con lo siguiente:

function myFunc1(){
    alert('a');
}


function myFunc2 (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Y un paradigma de objeto usando la Clase como prototipo de objeto:

function Class(){
    this.myFunc1 =  function(msg){
        alert(msg);
    }

    this.myFunc2 = function(callBackParameter){
        callBackParameter('message');
    }
}


function main(){    
    var myClass = new Class();  
    myClass.myFunc2(myClass.myFunc1);
}
 -2
Author: gazgas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-09 08:18:01