tipos - template string javascript
¿Cómo convertir una cadena en una función de llamada de JavaScript? (13)
Aquí hay una forma más genérica de hacer lo mismo, mientras se apoyan los ámbitos:
// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
var scope = window;
var scopeSplit = string.split(''.'');
for (i = 0; i < scopeSplit.length - 1; i++)
{
scope = scope[scopeSplit[i]];
if (scope == undefined) return;
}
return scope[scopeSplit[scopeSplit.length - 1]];
}
Espero que pueda ayudar a algunas personas.
Esta pregunta ya tiene una respuesta aquí:
Tengo una cadena como:
settings.functionName + ''('' + t.parentNode.id + '')'';
que quiero traducir en una función llamada así:
clickedOnItem(IdofParent);
Esto, por supuesto, tendrá que hacerse en JavaScript. Cuando hago una alerta en settings.functionName + ''('' + t.parentNode.id + '')'';
Parece que todo está correcto. Solo necesito llamar a la función que se traduciría.
Leyenda:
settings.functionName = clickedOnItem
t.parentNode.id = IdofParent
Basado en la respuesta de Nicolas Gauthier:
var strng = ''someobj.someCallback'';
var data = ''someData'';
var func = window;
var funcSplit = strng.split(''.'');
for(i = 0;i < funcSplit.length;i++){
//We maybe can check typeof and break the bucle if typeof != function
func = func[funcSplit[i]];
}
func(data);
En javascript que usa la especificación CommonJS, como por ejemplo node.js, puedes hacer lo que muestro a continuación. Lo cual es bastante útil para acceder a una variable por una cadena incluso si no está definida en el objeto de la window
. Si hay una clase llamada MyClass
, definida dentro de un módulo CommonJS llamado MyClass.js
// MyClass.js
var MyClass = function() {
// I do stuff in here. Probably return an object
return {
foo: "bar"
}
}
module.exports = MyClass;
A continuación, puede hacer este bonito bit o brujería desde otro archivo llamado MyOtherFile.js
// MyOtherFile.js
var myString = "MyClass";
var MyClass = require(''./'' + myString);
var obj = new MyClass();
console.log(obj.foo); // returns "bar"
Una razón más por la que CommonJS es un placer.
Esto me llevó un tiempo descifrarlo, ya que la window[''someFunctionName'']()
convencional window[''someFunctionName'']()
no me funcionó al principio. Los nombres de mis funciones fueron extraídos como una respuesta AJAX de una base de datos. Además, por cualquier motivo, mis funciones se declararon fuera del alcance de la ventana, así que para solucionar esto tuve que reescribir las funciones desde las que llamaba
function someFunctionName() {}
a
window.someFunctionName = function() {}
y desde allí podría llamar a la window[''someFunctionName'']()
con facilidad. ¡Espero que esto ayude a alguien!
JavaScript tiene una función eval
que evalúa una cadena y la ejecuta como código:
eval(settings.functionName + ''('' + t.parentNode.id + '')'');
Prefiero usar algo como esto:
window.callbackClass[''newFunctionName''] = function(data) { console.log(data) };
...
window.callbackClass[''newFunctionName''](data);
Quería poder tomar un nombre de función como una cadena, llamarlo y pasar un argumento a la función. No pude obtener la respuesta seleccionada para esta pregunta, pero esta answer explicó exactamente, y aquí hay una breve demostración.
function test_function(argument) {
alert(''This function '' + argument);
}
functionName = ''test_function'';
window[functionName](''works!'');
Esto también funciona con múltiples argumentos.
Si settings.functionName
ya es una función, puede hacer esto:
settings.functionName(t.parentNode.id);
De lo contrario, esto también debería funcionar si settings.functionName
es solo el nombre de la función:
if (typeof window[settings.functionName] == "function") {
window[settings.functionName](t.parentNode.id);
}
Si bien me gusta la primera respuesta y odio la evaluación, me gustaría agregar que hay otra forma (similar a la evaluación), por lo que si puedes rodearla y no usarla, es mejor que lo hagas. Pero en algunos casos es posible que desee llamar a algún código javascript antes o después de una llamada ajax y si tiene este código en un atributo personalizado en lugar de ajax, puede usar esto:
var executeBefore = $(el).attr("data-execute-before-ajax");
if (executeBefore != "") {
var fn = new Function(executeBefore);
fn();
}
O, finalmente, almacene esto en un caché de funciones si es posible que necesite llamarlo varias veces.
De nuevo, no uses eval o este método si tienes otra forma de hacerlo.
Viendo como odio eval, y no estoy solo :
var fn = window[settings.functionName];
if(typeof fn === ''function'') {
fn(t.parentNode.id);
}
Edición: En respuesta al comentario de @ Mahan: En este caso particular, settings.functionName
sería "clickedOnItem"
. Esto, en tiempo de ejecución, traducir var fn = window[settings.functionName];
en var fn = window["clickedOnItem"]
, que obtendría una referencia a la function clickedOnItem (nodeId) {}
. Una vez que tenemos una referencia a una función dentro de una variable, podemos llamar a esta función "llamando a la variable", es decir, fn(t.parentNode.id)
, que es igual a clickedOnItem(t.parentNode.id)
, que era lo que OP querido.
Más ejemplo completo:
/* Somewhere: */
window.settings = {
/* [..] Other settings */
functionName: ''clickedOnItem''
/* , [..] More settings */
};
/* Later */
function clickedOnItem (nodeId) {
/* Some cool event handling code here */
}
/* Even later */
var fn = window[settings.functionName];
/* note that settings.functionName could also be written
as window.settings.functionName. In this case, we use the fact that window
is the implied scope of global variables. */
if(typeof fn === ''function'') {
fn(t.parentNode.id);
}
eval () es la función que necesitas para hacer eso, pero te aconsejaría probar una de estas cosas para minimizar el uso de eval. Esperemos que uno de ellos tenga sentido para ti.
Almacenar la función
Almacene la función como una función, no como una cadena, y úsela como una función más adelante. Donde realmente almacenes la función depende de ti.
var funcForLater = clickedOnItem;
// later is now
funcForLater(t.parentNode.id);
o
someObject.funcForLater = clickedOnItem;
// later is now
(someObject.funcForLater)(t.parentNode.id);
Nombre de función de tienda
Incluso si tiene que almacenar el nombre de la función como una cadena, puede minimizar la complejidad haciendo
(eval(settings.functionName))(t.parentNode.id);
Lo que minimiza la cantidad de Javascript que tienes que construir y evaluar.
Diccionario de manipuladores
Coloque todas las funciones de acción que pueda necesitar en un objeto y llámelas al estilo de diccionario usando la cadena.
// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };
// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);
(Nota menor: si en su lugar aquí usó la sintaxis itemActions[actionName](t.parentNode.id);
entonces la función se llamará como un método de itemActions
).
eval("javascript code");
se utiliza ampliamente cuando se trata de JSON .
window[settings.functionName](t.parentNode.id);
No hay necesidad de una evaluación ()