Pregunta Cómo ejecutar una función de JavaScript cuando tengo su nombre como una cadena


Tengo el nombre de una función en JavaScript como una cadena. ¿Cómo convierto eso en un puntero de función para poder llamarlo más tarde?

Dependiendo de las circunstancias, es posible que deba pasar varios argumentos en el método también.

Algunas de las funciones pueden tomar la forma de namespace.namespace.function(args[...]).


848
2017-12-11 15:47


origen


Respuestas:


No use eval a menos que absolutamente, positivamente no tengo otra opción.

Como se ha mencionado, usar algo como esto sería la mejor manera de hacerlo:

window["functionName"](arguments);

Eso, sin embargo, no funcionará con una función de espacio de nombres:

window["My.Namespace.functionName"](arguments); // fail

Así es como lo harías:

window["My"]["Namespace"]["functionName"](arguments); // succeeds

Para hacerlo más fácil y proporcionar cierta flexibilidad, aquí hay una función de conveniencia:

function executeFunctionByName(functionName, context /*, args */) {
  var args = Array.prototype.slice.call(arguments, 2);
  var namespaces = functionName.split(".");
  var func = namespaces.pop();
  for(var i = 0; i < namespaces.length; i++) {
    context = context[namespaces[i]];
  }
  return context[func].apply(context, args);
}

Lo llamarías así:

executeFunctionByName("My.Namespace.functionName", window, arguments);

Tenga en cuenta que puede pasar en el contexto que desee, así que esto haría lo mismo que arriba:

executeFunctionByName("Namespace.functionName", My, arguments);

1224
2017-12-11 16:15



Solo pensé en publicar una versión ligeramente alterada de La muy útil función de Jason Bunting.

Primero, simplifiqué la primera declaración suministrando un segundo parámetro a rebanada(). La versión original funcionaba bien en todos los navegadores, excepto en IE.

Segundo, he reemplazado esta con contexto en la declaración de devolución; de otra manera, esta siempre estaba apuntando a ventana cuando la función objetivo se estaba ejecutando.

function executeFunctionByName(functionName, context /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    return context[func].apply(context, args);
}

89
2017-12-04 02:16



La respuesta a esta otra pregunta muestra cómo hacerlo: ¿JavaScript equivalente a los locales de Python ()?

Básicamente, puedes decir

window["foo"](arg1, arg2);

o como muchos otros han sugerido, puedes usar eval:

eval(fname)(arg1, arg2);

aunque esto es extremadamente inseguro a menos que esté absolutamente seguro de lo que está evaluando.


51
2017-12-11 15:49



¿No podrías simplemente hacer esto?

var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();

También puede ejecutar cualquier otro JavaScript utilizando este método.


43
2017-08-16 20:56



Creo que una forma elegante de hacerlo es definiendo tus funciones en un objeto hash. Entonces puede tener una referencia a esas funciones del hash usando la cadena. p.ej.

var customObject = {
  customFunction: function(param){...}
};

Entonces puedes llamar:

customObject['customFunction'](param);

Donde función personalizada será una cadena que coincida con una función definida en su objeto.


29
2018-06-02 17:13



Dos cosas:

  • evita la evaluación, es terriblemente peligroso y lento

  • en segundo lugar, no importa dónde exista su función, la "globalidad" es irrelevante. x.y.foo() se puede habilitar a través de x.y['foo']() o x['y']['foo']() o incluso window['x']['y']['foo'](). Puedes encadenarte indefinidamente así.


21
2017-12-11 16:01



Con ES6 puedes acceder a los métodos de clase por nombre:

class X {
  method1(){
    console.log("1");
  }
  method2(){
    this['method1']();
    console.log("2");
  }
}
let x  = new X();
x['method2']();

la salida sería:

1
2

18
2017-07-08 10:22



Solo necesitas convertir tu cadena en un puntero window[<method name>]. ejemplo:

var function_name = "string";
function_name = window[function_name];

y ahora puedes usarlo como un puntero.


12
2017-11-11 18:22