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 puedo convertir eso en un puntero de función para poder llamarlo más tarde?

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

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

preguntado el 11 de diciembre de 08 a las 13:12

30 Respuestas

No use eval a menos que usted 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 harías eso:

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

Para hacerlo más fácil y brindar 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, por lo que esto haría lo mismo que el anterior:

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

Respondido 28 ago 18, 09:08

¿Sabes que no necesitas todo el constructo "func"? "context.apply" solo está bien - Annakata

Claro, lo sé, pero la forma en que escribí la función proporciona cierta claridad para aquellos que la leen y que pueden no entender completamente lo que está sucediendo. Escribí esta función dándome cuenta de que la gente que la lee puede necesitar ayuda. Sin embargo, proporcionaré una alternativa, ya que preguntaste ... - jason empavesado

Borre eso: el código es lo suficientemente claro y aquellos que saben, lo saben. Si eres como yo y sabes lo que estás haciendo, puedes hacer esos cambios por tu cuenta si usaste este código. Stack Overflow es para educar a otros, y creo que mi código es más fácil de entender para los principiantes. Pero gracias! - jason empavesado

¿Existe una situación en la que la ventana ["funcName"] devuelva undefined? Ese es el problema que tengo en este momento. El código de llamada y la función se definen en dos archivos js separados. Intenté agregarlos al mismo archivo, pero eso no hizo ninguna diferencia. - código mono

Creo que aquí hay un problema. Cuando usted llama My.Namespace.functionName(), this se referirá a la My.Namespace objeto. Pero cuando llamas executeFunctionByName("My.Namespace.functionName", window), no hay forma de conseguir this para referirse a lo mismo. Tal vez debería usar el último espacio de nombres como ámbito, o window si no hay espacios de nombres. O puede permitir que el usuario especifique el alcance como un argumento. - JW.

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

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

Segundo, he reemplazado este con contexto en la declaración de devolución; de lo contrario, este siempre estaba apuntando a ventana cuando se estaba ejecutando la función de destino.

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);
}

contestado el 23 de mayo de 17 a las 13:05

¿No hay verificación para ver si "functionName" realmente existe? - Crashalot

Creo que la respuesta de Mac está subestimada. No soy un experto pero parece bien pensado y robusto. - Martín Hansen Lennox

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

Básicamente, puedes decir

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

o como muchos otros han sugerido, puede usar eval:

eval(fname)(arg1, arg2);

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

contestado el 23 de mayo de 17 a las 12:05

la primera forma es mucho preferible - Annakata

Solo use eval como último recurso, cuando todo lo demás falla. - jason empavesado

Lo es ... pero ¿funcionará con funciones como esta: xyz (args)? - Kieron

@keiron: sí. mira mi respuesta a continuación - Annakata

¿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.

Respondido 16 ago 13, 21:08

funciona cuando incluso se pasan argumentos con la función - adeel41

¿Qué pasa con el retorno de la función? - Pedro Denev

¿En qué se diferencia eso de eval("My.Namespace.functionName()");? - desarrolladorbmw

@PeterDenev solo cambia la primera línea a var codeToExecute = "return My.Namespace.functionName()"; - desarrolladorbmw

@developerbmw, aquí está la respuesta stackoverflow.com/questions/4599857/… - Tejasvi Hegde

Creo que una forma elegante de hacer esto es definiendo sus funciones en un objeto hash. Entonces puede tener una referencia a esas funciones desde el hash usando la cadena. p.ej

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

Entonces puedes llamar:

customObject['customFunction'](param);

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

ACTUALIZACIÓN

Parece que esta respuesta fue útil para muchos otros programadores, así que aquí va una versión actualizada.

Con ES6 puede utilizar adicionalmente Nombres de propiedades calculados lo que te permitirá evitar las cuerdas mágicas.

const FunctionNames = Object.freeze({ 
  FirstFunction: "firstFunction", 
  SecondFunction: "secondFunction" 
});

...

var customObject = {
  [FunctionNames.FirstFunction]: function(param){...},
  [FunctionNames.SecondFunction]: function(param){...}
};

...

customObject[FunctionNames.FirstFunction](param);

Respondido 26 Feb 21, 22:02

@ibsenv, gracias por tu comentario para ayudarme a identificar esta respuesta como la mejor. Creé una matriz de objetos de función y, a su vez, la usé para crear una matriz de promesas diferidas. Pongo un código de muestra a continuación. (No quería crear una nueva respuesta y pedir prestado Respuesta de Ruben.) - user216661

function getMyData (arrayOfObjectsWithIds) {var functionArray = arrayOfObjectsWithIds.map (function (value) {return {myGetDataFunction: MyService.getMyData (value.id)};}) var promises = functionArray.map (function (getDataFunction) {var deferred q.defer (); getDataFunction.myGetDataFunction.success (function (data) {deferred.resolve (data)}). error (function (error) {deferred.reject ();}); return deferred.promise;}); $ q.all (promesas) .then (function (dataArray) {// hacer cosas})}; - user216661

Esto funciona excelente, solo agrego subrayado / lodash para verificar si es una función. Y luego corre - elporfirio

Con ES6 puede acceder a los métodos de clase por su 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

Respondido 08 Jul 15, 11:07

Mejor javascript PURE ... Dios .. borrar la clase no funciona y está bien. ¡Gracias! - reyjinete

Esto es lo que estaba buscando desde hace mucho tiempo. ¡Gracias! - Paladín

ES2015 no tiene nada que ver aquí. Puede lograr el mismo objetivo utilizando objetos puros o la delegación de prototipos a través de Object.create(). const myObj = {método1 () {consola.log ('1')}, método2 () {consola.log ('2')}} myObj ['método1'] (); // 1 myObj ['método2'] (); // 2 - sminutoli

¡¡¡Esto es oro !!! Me sorprende no haber pensado en esto antes. ¡¡¡Lindo!!! - gracias

También creo que esta es la mejor manera de lograr nuestro objetivo. - Chris Jung

Dos cosas:

  • evitar eval, 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']() or x['y']['foo']() o incluso window['x']['y']['foo'](). Puedes encadenar indefinidamente así.

Respondido 11 Jul 15, 12:07

pero no puede hacer la ventana ['xyz'] () para llamar a xyz () - apodo

Todas las respuestas asumen que se puede acceder a las funciones a través del alcance global (ventana). Sin embargo, el PO no hizo esta suposición.

Si las funciones viven en un ámbito local (también conocido como cierre) y no son referenciadas por algún otro objeto local, mala suerte: tienes que usar eval() AFAIK, ver llamar dinámicamente a la función local en javascript

contestado el 22 de mayo de 20 a las 00:05

Amigo (o dudette), ¡muchas gracias por señalar eso! Pensé que me estaba volviendo loco por un segundo. - funktr0n

Dependiendo de dónde se encuentre, también puede usar:

this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();

o, en nodejs

global["funcname"]()

Respondido 25 Feb 19, 22:02

Gracias a esta respuesta, es posible hacerlo function callObjectMethod(obj,meth){ return (_v) => { obj[meth](_v) } }. Para mí, esto es útil para llamar a algún método de objeto con un parámetro que proviene de una devolución de llamada desde un servicio externo. Espero que esto ayude a alguien más. - enrique rene

Solo necesita convertir su cadena en un puntero por window[<method name>]. ejemplo:

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

y ahora puedes usarlo como un puntero.

respondido 11 nov., 11:21

Esta parece ser una forma mucho más segura. - james poulose

Aquí está mi contribución a las excelentes respuestas de Jason Bunting / Alex Nazarov, donde incluyo la verificación de errores solicitada por Crashalot.

Dado este preámbulo (artificial):

a = function( args ) {
    console.log( 'global func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] );
    }
};
ns = {};
ns.a = function( args ) {
    console.log( 'namespace func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] ); 
    }
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};

luego la siguiente función:

function executeFunctionByName( functionName, context /*, args */ ) {
    var args, namespaces, func;

    if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }

    if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }

    if( typeof context !== 'undefined' ) { 
        if( typeof context === 'object' && context instanceof Array === false ) { 
            if( typeof context[ functionName ] !== 'function' ) {
                throw context + '.' + functionName + ' is not a function';
            }
            args = Array.prototype.slice.call( arguments, 2 );

        } else {
            args = Array.prototype.slice.call( arguments, 1 );
            context = window;
        }

    } else {
        context = window;
    }

    namespaces = functionName.split( "." );
    func = namespaces.pop();

    for( var i = 0; i < namespaces.length; i++ ) {
        context = context[ namespaces[ i ] ];
    }

    return context[ func ].apply( context, args );
}

le permitirá llamar a una función javascript por su nombre almacenado en una cadena, ya sea con espacio de nombres o global, con o sin argumentos (incluidos los objetos Array), proporcionando retroalimentación sobre cualquier error encontrado (con suerte, detectándolos).

La salida de muestra muestra cómo funciona:

// calling a global function without parms
executeFunctionByName( 'a' );
  /* OUTPUT:
  global func passed:
  */

// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
  /* OUTPUT:
  global func passed:
  -> 123
  */

// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
  /* OUTPUT:
  namespace func passed:
  */

// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  */

// calling a namespaced function, with explicit context as separate arg, passing a string literal and array 
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  -> 7,is the man
  */

// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
  /* OUTPUT:
  global func passed:
  -> nsa
  */

// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
  /* OUTPUT:
  Uncaught n_s_a is not a function
  */

// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
  /* OUTPUT:
  Uncaught Snowden is not a function
  */

// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
  /* OUTPUT:
  Uncaught [object Object].a is not a function
  */

// calling no function
executeFunctionByName();
  /* OUTPUT:
  Uncaught function name not specified
  */

// calling by empty string
executeFunctionByName( '' );
  /* OUTPUT:
  Uncaught  is not a function
  */

// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
  /* OUTPUT:
  Uncaught [object Object].noSuchAgency is not a function
  */

Respondido 11 Feb 17, 01:02

No sé ... es un muy buen esfuerzo, así de claro. Pero suena como "demasiado amplio" para mí ... - TechNyquist

¿Eh? SO es una plataforma de preguntas / respuestas / enseñanza. Con mucho gusto proporcionaré todos los ejemplos que se me ocurran para, con suerte, transmitir iluminación. A mi, ese es el punto. - Mac

Si está evaluando el functionName de todos modos, ¿por qué no usarlo? - datos

Esto no me funciona. Tengo una función de espacio de nombres abcd donde d es el nombre de la función. la llamada executeFunctionByName ("abcd", ventana) falla en la línea que verifica if( typeof context[ functionName ] !== 'function' ) porque el contexto - ventana - está definido, es un objeto y una matriz, pero la ventana ['abcd'] no existe ya que se identificó como un problema en la respuesta aceptada: window["My.Namespace.functionName"](arguments); // fail - Akousmata

Si desea llamar a una función de un objeto en lugar de una función global con window["functionName"]. Puedes hacerlo como;

var myObject=new Object();
myObject["functionName"](arguments);

Ejemplo:

var now=new Date();
now["getFullYear"]()

Respondido el 25 de enero de 13 a las 13:01

¡¡¡TEN CUIDADO!!!

Uno debería intentar evitar llamar a una función por cadena en JavaScript por dos razones:

Razón 1: Algunos ofuscadores de código arruinarán su código ya que cambiarán los nombres de las funciones, haciendo que la cadena sea inválida.

Razón 2: Es mucho más difícil mantener el código que usa esta metodología, ya que es mucho más difícil ubicar los usos de los métodos llamados por una cadena.

Respondido 20 ago 14, 15:08

Aquí está mi enfoque Es6 que le permite llamar a su función por su nombre como cadena o su nombre de función y también le permite pasar diferentes números de argumentos a diferentes tipos de funciones:

function fnCall(fn, ...args)
{
  let func = (typeof fn =="string")?window[fn]:fn;
  if (typeof func == "function") func(...args);
  else throw new Error(`${fn} is Not a function!`);
}


function example1(arg1){console.log(arg1)}
function example2(arg1, arg2){console.log(arg1 + "  and   " + arg2)}
function example3(){console.log("No arguments!")}

fnCall("example1", "test_1");
fnCall("example2", "test_2", "test3");
fnCall(example3);
fnCall("example4"); // should raise an error in console

Respondido 21 Abr '20, 16:04

Sorprendido de no ver ninguna mención de setTimeout.

Para ejecutar una función sin argumentos:

var functionWithoutArguments = function(){
    console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);

Para ejecutar la función con argumentos:

var functionWithArguments = function(arg1, arg2) {
    console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");

Para ejecutar una función profundamente espaciada de nombres:

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}
setTimeout("_very._deeply._defined._function(40,50)", 0);

Respondido 17 Oct 14, 22:10

Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación; siempre puede comentar sus propias publicaciones, y una vez que tenga suficiente reputación usted será capaz de comenta en cualquier publicación. - AstroCB

Agregue un ejemplo de cómo llamaría runMe con algunos argumentos. - léxico

@lexicore he votado por eliminación en una cola de revisión, porque no con claridad. proporcionar una respuesta sustancial a la pregunta y es de poco valor por sí sola. - AstroCB

Este método tiene un defecto potencialmente enorme, ya que pone la ejecución a fin de renderizado cola, haciendo esta llamada asincrónico - PedroM

Me gusta esta respuesta, parece funcionar para mis requisitos. - Quinton

No creo que necesite funciones intermedias complicadas o eval o dependa de variables globales como window:

function fun1(arg) {
  console.log(arg);
}

function fun2(arg) {
  console.log(arg);
}

const operations = {
  fun1,
  fun2
};

operations["fun1"]("Hello World");
operations.fun2("Hello World");

// You can use intermediate variables, if you like
let temp = "fun1";
operations[temp]("Hello World");

También funcionará con funciones importadas:

// mode.js
export function fun1(arg) {
  console.log(arg);
}

export function fun2(arg) {
  console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";

const operations = {
  fun1,
  fun2
};

operations["fun1"]("Hello World");
operations["fun2"]("Hello World");

Dado que está utilizando el acceso a la propiedad, sobrevivirá a la minimización u ofuscación, al contrario de algunas respuestas que encontrará aquí.

Respondido 22 Jul 20, 12:07

Entonces, como dijeron otros, definitivamente la mejor opción es:

window['myfunction'](arguments)

Y, como Jason Bunting dijo, no funcionará si el nombre de su función incluye un objeto:

window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work

Así que aquí está mi versión de una función que ejecutará todas las funciones por nombre (incluido un objeto o no):

my = {
    code : {
        is : {
            nice : function(a, b){ alert(a + "," + b); }
        }
    }
};

guy = function(){ alert('awesome'); }

function executeFunctionByName(str, args)
{
    var arr = str.split('.');
    var fn = window[ arr[0] ];
    
    for (var i = 1; i < arr.length; i++)
    { fn = fn[ arr[i] ]; }
    fn.apply(window, args);
}

executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');

contestado el 23 de mayo de 17 a las 13:05

  let t0 = () => { alert('red0') }
  var t1 = () =>{ alert('red1') }
  var t2 = () =>{ alert('red2') }
  var t3 = () =>{ alert('red3') }
  var t4 = () =>{ alert('red4') }
  var t5 = () =>{ alert('red5') }
  var t6 = () =>{ alert('red6') }

  function getSelection(type) {
    var evalSelection = {
      'title0': t0,
      'title1': t1,
      'title2': t2,
      'title3': t3,
      'title4': t4,
      'title5': t5,
      'title6': t6,
      'default': function() {
        return 'Default';
      }
    };
    return (evalSelection[type] || evalSelection['default'])();
  }
  getSelection('title1');

Una solución más orientada a objetos ...

Respondido el 27 de junio de 17 a las 14:06

Un detalle más sobre las publicaciones de Jason y Alex. Me resultó útil agregar un valor predeterminado al contexto. Sólo hay que poner context = context == undefined? window:context; al comienzo de la función. Tu puedes cambiar window a cualquiera que sea su contexto preferido, y luego no necesitará pasar la misma variable cada vez que llame a esto en su contexto predeterminado.

Respondido el 28 de diciembre de 12 a las 05:12

Para agregar a la respuesta de Jason Bunting, si está usando nodejs o algo así (y esto también funciona en dom js), podría usar this en lugar de window (y recuerda: eval es mal:

this['fun'+'ctionName']();

Respondido el 29 de junio de 14 a las 17:06

Hay algo muy similar en mi código. Tengo una cadena generada por el servidor que contiene un nombre de función que necesito pasar como devolución de llamada para una biblioteca de terceros. Entonces tengo un código que toma la cadena y devuelve un "puntero" a la función, o nulo si no se encuentra.

Mi solución fue muy similar a "La función muy útil de Jason Bunting" *, aunque no se ejecuta automáticamente y el contexto siempre está en la ventana. Pero esto se puede modificar fácilmente.

Con suerte, esto será útil para alguien.

/**
 * Converts a string containing a function or object method name to a function pointer.
 * @param  string   func
 * @return function
 */
function getFuncFromString(func) {
    // if already a function, return
    if (typeof func === 'function') return func;

    // if string, try to find function or method of object (of "obj.func" format)
    if (typeof func === 'string') {
        if (!func.length) return null;
        var target = window;
        var func = func.split('.');
        while (func.length) {
            var ns = func.shift();
            if (typeof target[ns] === 'undefined') return null;
            target = target[ns];
        }
        if (typeof target === 'function') return target;
    }

    // return null if could not parse
    return null;
}

contestado el 23 de mayo de 17 a las 13:05

También hay una forma muy útil.

http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx

var arrayMaker = {  
    someProperty: 'some value here',  
    make: function (arg1, arg2) {  
        return [ this, arg1, arg2 ];  
    },
    execute: function_name
};

respondido 23 nov., 12:00

No puedo resistirme a mencionar otro truco, que ayuda si tiene un número desconocido de argumentos que también se pasan como parte de la cadena que contiene el nombre de la función. Por ejemplo:

var annoyingstring = 'call_my_func(123, true, "blah")';

Si su Javascript se ejecuta en una página HTML, todo lo que necesita es un enlace invisible; puedes pasar una cuerda en el onclick atributo, y la llamada al click método.

<a href="#" id="link_secret"><!-- invisible --></a>

$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();

O crea el <a> elemento en tiempo de ejecución.

Respondido 29 Oct 15, 12:10

Solución creativa, pero esto no funcionará para argumentos de tipo objeto o matriz. - dennis heiden

Esto es usar eval bajo el capó ... Y realmente andando por las ramas para hacerlo - Juan mendes

La forma más fácil es acceder a él como si fuera un elemento.

window.ClientSideValidations.forms.location_form

es igual que

window.ClientSideValidations.forms['location_form']

Respondido 20 Abr '16, 08:04

Look básico:

var namefunction = 'jspure'; // String

function jspure(msg1 = '', msg2 = '') { 
  console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument

// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple

Existe otro tipo de función es clase y mira el ejemplo nils petersohn

Respondido el 03 de junio de 16 a las 15:06

Gracias por la respuesta tan útil. Estoy usando Función de Jason Bunting en mis proyectos.

Lo extendí para usarlo con un tiempo de espera opcional, porque la forma normal de establecer un tiempo de espera no funcionará. Ver pregunta de abhishekisnot

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

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}

console.log('now wait')
executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );

contestado el 23 de mayo de 17 a las 13:05

Existen varias executeByName funciones aquí que funciona bien, a menos que el nombre contenga corchetes - problema con el que me encontré, ya que he generado nombres dinámicamente. Entonces, las funciones anteriores fallarán en nombres como

app.widget['872LfCHc']['toggleFolders']

Como remedio, he hecho una función para tener esto en cuenta también, tal vez alguien lo encuentre útil:

Generado a partir de CoffeeScript:

var executeByName = function(name, context) {
  var args, func, i, j, k, len, len1, n, normalizedName, ns;
  if (context == null) {
    context = window;
  }
  args = Array.prototype.slice.call(arguments, 2);
  normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.');
  ns = normalizedName.split(".");
  func = context;
  for (i = j = 0, len = ns.length; j < len; i = ++j) {
    n = ns[i];
    func = func[n];
  }
  ns.pop();
  for (i = k = 0, len1 = ns.length; k < len1; i = ++k) {
    n = ns[i];
    context = context[n];
  }
  if (typeof func !== 'function') {
    throw new TypeError('Cannot execute function ' + name);
  }
  return func.apply(context, args);
}

Para una mejor legibilidad, compruebe también la versión de CoffeeScript:

executeByName = (name, context = window) ->
    args = Array.prototype.slice.call(arguments, 2)
    normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.')
    ns = normalizedName.split "."
    func = context
    for n, i in ns
        func = func[n]

    ns.pop()
    for n, i in ns
        context = context[n];
    if typeof func != 'function'
        throw new TypeError 'Cannot execute function ' + name
    func.apply(context, args)

respondido 15 nov., 16:10

Puede llamar a la función javascript dentro de la eval("functionname as string") ya sea. Como a continuación: (eval es una función pura de JavaScript)

function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});

Ejemplo de trabajo: https://jsfiddle.net/suatatan/24ms0fna/4/

Respondido el 16 de enero de 17 a las 13:01

Esto funciona bien y es tan simple. Carlos E.

Y también muy lento. - Marco

todo lo que tiene que hacer es usar un contexto o definir un nuevo contexto donde residen sus funciones. no estás limitado a window["f"]();

aquí hay un ejemplo de cómo utilizo alguna invocación dinámica para algunos servicios REST.

/* 
Author: Hugo Reyes
@ www.teamsrunner.com

*/

    (function ( W, D) { // enclose it as self invoking function to avoid name collisions.


    // to call function1 as string
    // initialize your FunctionHUB as your namespace - context
    // you can use W["functionX"](), if you want to call a function at the window scope.
    var container = new FunctionHUB();


    // call a function1 by name with one parameter.

    container["function1"](' Hugo ');


    // call a function2 by name.
    container["function2"](' Hugo Leon');


    // OO style class
    function FunctionHUB() {

        this.function1 = function (name) {

            console.log('Hi ' + name + ' inside function 1')
        }

        this.function2 = function (name) {

            console.log('Hi' + name + ' inside function 2 ')
        }
    }

})(window, document); // in case you need window context inside your namespace.

Si desea generar la función completa a partir de una cadena, esa es una respuesta diferente. También tenga en cuenta que no está limitado a un solo espacio de nombre, si el espacio de nombre existe como my.name.space.for.functions.etc.etc.etc la última rama de su espacio de nombre contiene la función como my.name.space.for.functions.etc.etc["function"]();

Espero eso ayude. H.

Respondido el 07 de Septiembre de 17 a las 09:09

Esto es trabajo para mí:

var command = "Add";
var tempFunction = new Function("Arg1","Arg2", "window." + command + "(Arg1,Arg2)");
tempFunction(x,y);

Espero que esto funcione.

Respondido 05 Oct 17, 03:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.