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 que eval 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 eval1

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 de Function también es una forma de eval. setTimeout cuando le pasas una string también usa el intérprete, igual que los atributos onclick, onmouseover... (aunque en éste caso por comodidad en un blog pueda estar justificado).