Evitar el uso de eval() en Javascript
Jueves, Noviembre 6, 2008Hoy 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?

