Evitar el uso de eval() en Javascript
Hoy en el trabajo he descubierto que la función eval() de Javascript y Firebug se llevan muy mal. Tan mal que no conseguía depurar una clase que estoy desarrollando. Googleando un poco he conseguido encontrar varias formas de evitar eval() y algunos motivos por lo que es recomendable evitar su uso.
El funcionamiento de eval() es el siguiente:
- Se convierte el argumento en un String.
- Se parsea el String y se convierte en código Javascript.
- Se ejecuta el código Javascript resultante.
Evidentemente saltarse los pasos 1 y 2 mejora el rendimiento. Además evita esos problemas “raros” que he comentado antes con Firebug.
En concreto los problemas con los que me he encontrado incluían los siguientes usos de eval:
- Asignar una propiedad a un objeto cuyo nombre está almacenado en un String.
- Llamar a una función cuyo nombre está almacenado en un String.
- Crear un objeto de una clase cuyo nombre está almacenado en un String.
Es decir, tres casos muy parecidos que se reducen a uno solo, acceder a variables cuyo nombre conocemos a posteriori. Para solucionar esto basta con saber que hay varias formas de acceder a una propiedad de un objeto en Javascript. La típica:
-
objeto.atributo = valor
y la no tan típica:
-
var nombreDelAtributo="atributo";
-
objeto[nombreDelAtributo] = valor;
Ahora solo falta saber otra cosa. Cualquier variable se puede acceder también como un atributo del objeto window, un ejemplo:
-
var cadena = "Hola mundo!";
-
alert(window.cadena); //mostrará un alert con "Hola mundo!"
-
alert(window[‘cadena’]); //también mostrara un alert con "Hola mundo!"
Ahora veamos algunos ejemplos de usos de eval() y otras formas de avordar el mismo problema.
-
/*
-
*asignar un valor a un atributo cuyo nombre no conocemos a priori
-
*/
-
eval(‘objecto.’ + nombreDelAtributo + ‘=valorDelAtributo’);
-
//se podría cambiar por
-
objeto[nombreDelAtributo] = valorDelAtributo;
-
-
/*
-
* Llamar a un metodo de un objeto estando el nombre del metodo almacenado en una variable
-
*/
-
-
eval(‘objeto.’ + nombreDelMetodo + ‘(argumento)’);
-
//podría ser
-
objeto[nombreDelMetodo](argumento);
-
-
/*
-
* Crear un objeto de una clase teniendo el nombre de la clase en una variable
-
*/
-
-
eval(‘var objeto = new ‘ + nombreDeLaClase + ‘()’);
-
//sería
-
var objeto = new window[nombreDeLaClase]();
En el último ejemplo podemos hacer esto por que una clase es también una variable del programa, y como tal se almacena como un atributo del objeto window.
Y vosotros, ¿usáis eval() en vuestro código? ¿conocíais estas soluciones?
No hay posts relacionados.


Noviembre 28th, 2008 at 22:47
Hola, pues interesante el articulo, yo siempre he evitado eval por los supuestos riesgos en la seguridad. Conocía los métodos de acceder variables y los uso muy seguido, especialmente cuando estoy creando objetos, aun que no había notado la relación que hay entre estos y eval. Muy interesante sin duda.
Por cierto, sin afán de iniciar un debate, pero que no se supone que Javascript no está basado en clases sino en prototipos? bueno, eso es solo un comentario, pero en realidad no es muy importante.
Saludos.
Noviembre 29th, 2008 at 0:06
Hola Buzu,
Sí, llevas razón, está basado en prototipos, pero usando algún framework, como Prototype, se consigue una abstracción mayor, que oculta el uso de los prototipos al programador y que hace la orientación a objetos de Javascript más parecida a la de otros lenguajes como Java. Por esto es por lo que he dicho que estoy haciendo una “clase”
Saludos!
Enero 21st, 2009 at 23:32
Oye es muy buena tu explicacion pero tengo un pequeño problema estoy usando Ajax para pasar un arreglo multidimensional desde un servlet en java hacia una pagina web el servlet me regresa un texto el cual yo interpreto como un comando javascript ejem Array(”tex1″, “tex2″, “texN”), el cual si es simple lo hace perfectamente, pero si paso un texto que simule un arreglo multidimensional no me funciona, que otra instruccion puedo usar para representar un texto como comando de javascript.
Enero 24th, 2009 at 14:00
@Erikcq Si te entiendo bien lo que haces es devolver un script Javascrip desde un servlet tras una petición AJAX. ¿Has probado a devolver los datos en otro formato como JSON o XML y crear ese array (o arreglo, como prefieras) desde Javascript? A mí me parece la forma más simple y es lo que suelo hacer.
Un saludo.
Febrero 12th, 2009 at 23:00
EXCELENTE. estaba usando una psclase con jquery al que le pasaba funcion como parametro y al hacer click en mya_b ejecutar la funcion y la matriz:
mya_b.bind("click",function(){
var thisreturn = new Array();
$(par).each(function (i, n){
thisreturn[n]= $("#boxiframe").contents().find("#"+n).val(); })
window[func](thisreturn);
});
Muchas gracias
Abril 7th, 2009 at 11:33
Hola.
Necesito ejecutar una función javascript cuyo nombre esta definido en una variable. Ha dicha función la tengo que pasar una serie de parámetros. Segun he estado viendo en lo publicado tendría que hacer algo asi
/*
* Llamar a un metodo de un objeto estando el nombre del metodo almacenado en una variable
*/
eval(‘objeto.’ + nombreDelMetodo + ‘(argumento)’);
//podría ser
objeto[nombreDelMetodo](argumento);
Pero tengo una duda, ¿que es objeto? he realizado una prueba y no me funciona.
Muchas gracias.
Abril 7th, 2009 at 12:26
Hola de nuevo!!!
Ya me funciona. En vez de objeto puse window y ya hace lo que yo quiero.
Muchas gracias por este articulo.
Un saludo.