Siguiendo con la serie dedicada al javascript[1,2,3], en esta entrada voy a indicar algunas de las cosas que nunca deberías hacer para escribir código eficiente y libre de errores.
No uses eval
Es una de las funciones que (salvo muy contadas excepciones deberías usar). eval
«evalúa» una string, es decir, la ejecuta como si fuera javascript.
Por ejemplo: var suma = eval("2 + 2"); // suma ahora es 4
.
Pero tiene varios problemas:
- Es lento:
eval
llama al intérprete de javascript, lo que es más lento que cualquier otro método que consiga el mismo resultado. - Es inseguro.
eval
se ha usado para muchas cosas, como conseguir objetos desde JSON. El problema es queeval
no evalúa sólo JSON. Supongamos que esperamos recibir un objeto JSON de una aplicación web, pero que esa aplicación está contaminada. Estarás ejecutando código maligno en el ordenador del espectador con todos tus privilegios. Actualmente es más fácil usar el objeto JSON (JSON.parse("{...}")
).
Conclusión: Salvo extrema necesidad, no uses eval
1
No uses los constructores de objetos
Usar los constructores de objetos (no todos, me refiero a Array
, Number
, Boolean
, String
, Function
, Object
) es una forma algo tonta de procesar. Usando, por ejemplo new String("Hola")
creas un objeto, no una string.
typeof ( new String("Hola") );// "object"
typeof "Hola"; // "string"
typeof ( new Boolean(null) );//"object"
// Para convertir cualquier valor a un boolean sin usar el constructor, se niega 2 veces
typeof !!null;//"boolean"
No uses nunca los operadores == y !=
En la entrada anterior, vimos las comparaciones. Los operadores ==
y !=
son operadores que tratan de convertir el tipo de los operandos. Sin embargo, ===
y !==
no lo hacen. Veamos un ejemplo:
var a = 1,
b = "000000001";
a == b //true, "b" es convertido a un número, lo que lo hace igual
a === b // false, porque "b" es una string
a === parseInt(b, 10) //true, porque b ahora es un número (más info sobre parseInt y parseFloat -> https://developer.mozilla.org/es/Gu%C3%ADa_JavaScript_1.5/Funciones_predefinidas/Funciones_parseInt_y_parseFloat)
a = new String("Hola mundo");
b = "Hola mundo" // Haz siempre esto ;)
a == b; // true
a === b; // false, a es un objeto, mientras b es una string
a.toString() === b //true, ahora a también es una string
Usa siempre var
Por poder, puedes declarar una variable sin usar la palabra var
. Es posible, pero estarás creando una variable global (y créeme, no quieres hacer eso).
El motivo para usarla siempre, viene explicado más abajo, y es el scope ¿tal vez en español ámbito (nunca lo he oído)? de las variables.
Usa siempre funciones anónimas
En javascript una variable está sólo disponible en la función en la que se declara (esto es lo que comentaba en el párrafo de arriba):
function cualquiera(){
var x = 2;
}
cualquiera()
console.log(x) //undefined, x no está disponible fuera de la función
var miDiaFavorito = "Lunes";// Ni de coña ;)
function cambiarDiaFavorito(){
miDiaFavorito = "Viernes"; // Esta variable está disponible dentro de la función, porque se declaró fuera
}
console.log(miDiaFavorito); // "Lunes"
cambiarDiaFavorito()
console.log(miDiaFavorito); // "Viernes"
Como lo más probable es que no quieras crear muchas variables o funciones globales, lo mejor es usar funciones anónimas autoinvocadas, y desde dentro declarar global lo que te interesa:
/* =Supongamos que quiero hacer una función para operar números.
Para ello haremos 4 funciones: sumar, dividir, restar y multiplicar
Pero queremos que fuera sólo esté disponible la de operar
*/
/*Si no usamos esta línea y la última, estarán disponibles fuera todas las funciones*/
(function(){
function sumar(num1, num2){
return num1 + num2;
}
function restar(num1, num2){
return num1 - num2;
}
function multiplicar(num1, num2){
return num1 * num2;
}
function dividir(num1, num2){
return num1 / num2;
}
function operar(num1, num2, operacion){
// En vez de condicionales podríamos usar switch, pero creo que así se entiende.
if( operacion === "suma") {return sumar(num1,num2);}
// Tened en cuenta que al usar return la función ya no ejecuta más código, así que no tiene sentido usar "else if"
if( operacion === "resta"){ return restar(num1,num2);}
if( operacion === "multiplicacion"){ return multiplicar(num1,num2);}
// Si no es ninguno de los tres (la función ya habría parado), sólo nos queda dividir
return dividir(num1,num2)
}
// Si "pasamos" la función operar a window (el objeto global), podemos acceder a ella desde fuera
window.operar = operar;
})()/*Los dos últimos paréntesis son para que la función se ejecute (pensad en cambiarDiaFavorito())*/
alert( operar(8,90, "division"))//0.088888888...
La función anónima se puede dividir en dos partes:
- Una es la función encerrada entre paréntesis:
(function(){/*código*/})
- La otra es la parte en la que llamamos a la función. Igual que para llamar a
cambiarDiaFavorito
usamos dos paréntesis (cambiarDiaFavorito()
), a esta también hay que llamarla:()
, si no no se ejecutará.
Espero que te haya sido útil para mejorar, y si has visto algún error, o tienes alguna duda, comenta por aquí y te responderé lo antes posible.
- 1 Ten en cuenta que
eval
no es sólo esa función. El constructor deFunction
también es una forma de eval.setTimeout
cuando le pasas una string también usa el intérprete, igual que los atributosonclick, onmouseover...
(aunque en éste caso por comodidad en un blog pueda estar justificado).