10 errores que suelen cometer los principiantes de JavaScript

JavaScript es un lenguaje fácil para empezar, pero dominarlo requiere mucho esfuerzo. Los principiantes a menudo cometen algunos errores bien conocidos que vuelven y los muerden cuando menos lo esperan. Para descubrir cuáles son estos errores, ¡sigue leyendo!

1. Faltan llaves

Una práctica, de la que los principiantes de JavaScript suelen ser culpables, es omitir llaves después de declaraciones como if , else , while y for . Aunque está permitido, debe tener mucho cuidado, ya que esta práctica a menudo puede ocultar problemas y ser la fuente de errores. Vea el siguiente ejemplo:

// Say hello to Gandalf
hello('Gandalf');

function hello(name){

    // This code doesn't do what the indentation implies!

    if(name === undefined)
        console.log('Please enter a username!');
        fail();

    // The following line is never reached:

    success(name);
}

function success(name){
    console.log('Hello, ' + name + '!');
}

function fail(){
    throw new Error("Name is missing. Can't say hello!");
}

Aunque el fail() la llamada está sangrada y parece que pertenece al if declaración, no lo hace. Siempre se llama. Por lo tanto, es una buena práctica rodear siempre los bloques de código con llaves, incluso si solo hay una declaración involucrada.

2. Puntos y comas faltantes

Cuando se analiza JavaScript, hay un proceso conocido como inserción automática de punto y coma. Como sugiere el nombre, el analizador se complace en insertar los puntos y comas faltantes por usted. El propósito de esta función es hacer que JavaScript sea más accesible y fácil de escribir para los principiantes. Sin embargo, siempre debe incluir puntos y comas, porque hay peligros en omitirlos. Aquí hay un ejemplo:

// This code results in a type error. Adding semicolons will fix it.

console.log('Welcome the fellowship!')

['Frodo', 'Gandalf', 'Legolas', 'Gimli'].forEach(function(name){
    hello(name)
})

function hello(name){
    console.log('Hello, ' + name + '!')
}

Debido a que falta un punto y coma en la línea 3, el analizador asume que el paréntesis de apertura en la línea 5 es un intento de acceder a una propiedad utilizando la sintaxis de acceso a la matriz (consulte el error n.º 8) y no una matriz separada, que no es lo que era. previsto y da como resultado un error de tipo. La solución es simple:siempre escribe punto y coma.

Algunos desarrolladores de JavaScript experimentados prefieren omitir los puntos y comas, pero son perfectamente conscientes de los errores que esto podría causar y saben cómo prevenirlos.

3. No entender el tipo de coerción

JavaScript se escribe dinámicamente. Esto significa que no necesita especificar un tipo al declarar una nueva variable, y puede reasignar o convertir libremente su valor. Esto hace que JavaScript sea mucho más fácil de escribir que algo como C# o Java, pero abre las puertas a posibles errores que en otros lenguajes se detectan durante el paso de compilación. Aquí hay un ejemplo:

// Listen for the input event on the textbox

var textBox = document.querySelector('input');

textBox.addEventListener('input', function(){

    // textBox.value holds a string. Adding 10 appends 
    // the string '10', it doesn't perform an addition..

    console.log(textBox.value + ' + 10 = ' + (textBox.value + 10));

});
<input type="number" placeholder="Enter a number here" />

El problema se puede solucionar fácilmente usando parseInt(textBox.value, 10) para convertir la cadena en un número antes de sumarle 10. Dependiendo de cómo use una variable, el tiempo de ejecución puede decidir que debe convertirse en un tipo u otro. Esto se conoce como coerción de tipos. Para evitar que los tipos se conviertan implícitamente al comparar variables en if declaraciones, puede utilizar comprobaciones estrictas de igualdad (===).

4. Olvidando var

Otra práctica de la que son culpables los principiantes es olvidarse de usar el var palabra clave al declarar variables. JavaScript es muy permisivo, y la primera vez que ve que has usado una variable sin el var declaración, lo declarará en silencio para usted a nivel mundial. Esta puede ser la fuente de errores sutiles. Aquí hay un ejemplo, que también muestra un error diferente:falta una coma al declarar varias variables a la vez:

var a = 1, b = 2, c = 3;

function alphabet(str){
    var a = 'A', b = 'B'    // Oops, missing ',' here!
        c = 'C', d = 'D';

    return str + ' ' + a + b + c + '…';
}

console.log( alphabet("Let's say the alphabet!") );

// Oh no! Something went wrong! c has a new value!
console.log(a, b, c);

Cuando el analizador llegue a la línea 4, insertará un punto y coma automáticamente y luego interpretará el c y d declaraciones en la línea 5 como global. Esto hará que cambie el valor de la variable exterior c. Lee más errores de JavaScript aquí.

5. Operaciones aritméticas con flotantes

Este error es cierto para casi todos los lenguajes de programación, incluido JavaScript. Debido a la forma en que se representan los números de punto flotante en la memoria, las operaciones aritméticas no son tan precisas como crees. Aquí hay un ejemplo:

var a = 0.1, b = 0.2;

// Surprise! this is false:
console.log(a + b == 0.3);

// Because 0.1 + 0.2 does not produce the number that you expect:
console.log('0.1 + 0.2 = ', a + b);

Para solucionar este problema, no debe usar decimales si necesita una corrección absoluta; use números enteros, o si necesita trabajar con dinero, use una biblioteca como bignumber.js.

6. Usando constructores sobre literales

Cuando los programadores de Java y C# comienzan a escribir JavaScript, a menudo prefieren crear objetos usando constructores:new Array() , new Object() , new String() . Aunque están perfectamente soportados, se recomienda utilizar las notaciones literales:[] , {} , "" , porque las funciones constructoras tienen peculiaridades sutiles:

/* Using array constructors is valid, but not recommended. Here is why. */

// Create an array with four elements:

var elem4 = new Array(1,2,3,4);

console.log('Four element array: ' + elem4.length);

// Create an array with one element. It doesn't do what you think it does:

var elem1 = new Array(23);

console.log('One element array? ' + elem1.length);

/* String objects also have their warts */

var str1 = new String('JavaScript'),
    str2 = "JavaScript";

// Strict equality breaks:

console.log("Is str1 the same as str2?", str1 === str2);

La solución es simple:trate de usar siempre la notación literal. Además, las matrices JS no necesitan saber su longitud por adelantado.

7. No entender cómo funcionan los alcances

Un concepto difícil de entender para los principiantes son las reglas de alcance y los cierres de JavaScript. Y con razón:

// Print the numbers from 1 to 10, 100ms apart. Or not.

for(var i = 0; i < 10; i++){
    setTimeout(function(){
        console.log(i+1);
    }, 100*i);
}

/* To fix the bug, wrap the code in a self-executing function expression:

for(var i = 0; i < 10; i++){

    (function(i){
        setTimeout(function(){
            console.log(i+1);
        }, 100*i);
    })(i);

}               

*/

Las funciones conservan la visibilidad de las variables en sus ámbitos principales. Pero debido a que estamos retrasando la ejecución con un setTimeout , cuando llega el momento de ejecutar las funciones, el bucle ya ha terminado y el i la variable se incrementa a 11.

La función autoejecutable en el comentario funciona, porque copia el i variable por valor y mantiene una copia privada para cada función de tiempo de espera. Obtenga más información sobre los alcances aquí y aquí.

8. Usando evaluación

Eval es malvado. Se considera una mala práctica y, la mayoría de las veces, cuando se usa, existe un enfoque mejor y más rápido.

/* Using eval to access properties dynamically */

var obj = {
    name: 'Foo Barski',
    age: 30,
    profession: 'Programmer'
};

// Which property to access?
var access = 'profession';

// This is a bad practice. Please don't do it:
console.log( eval('obj.name + " is a " + obj.' + access) );

// Instead, use array notation to access properties dynamically:
console.log( obj.name + " is a " + obj[access]);

/* Using eval in setTimout */

// Also bad practice. It is slow and difficult to read and debug:
setTimeout(' if(obj.age == 30) console.log("This is eval-ed code, " + obj[access] + "!");', 100);

// This is better:
setTimeout(function(){

    if(obj.age == 30){
        console.log('This code is not eval-ed, ' + obj[access] + '!');
    }

}, 100);

Código dentro de eval es una cadena. Los mensajes de depuración que surgen de los bloques de evaluación son incomprensibles y debe hacer malabarismos con el escape de comillas simples y dobles. Sin mencionar que es más lento que JavaScript normal. No utilice eval a menos que sepa lo que está haciendo.

9. No entender el código asíncrono

Algo que es exclusivo de JavaScript es que casi todo es asincrónico y es necesario pasar funciones de devolución de llamada para recibir notificaciones de eventos. Esto no es intuitivo para los principiantes, y rápidamente se encuentran rascándose la cabeza con un error que es difícil de entender. Aquí hay un ejemplo, en el que uso el servicio FreeGeoIP para obtener su ubicación por IP:

var userData = {};

// Fetch the location data for the current user.
load();

// Output the location of the user. Oops, it doesn't work! Why?
console.log('Hello! Your IP address is ' + userData.ip + ' and your country is ' + userData.country_name);

// The load function will detect the current visitor's ip and location with ajax, using the
// freegeoip service. It will place the returned data in the userData variable when it's ready.

function load(){

    $.getJSON('https://freegeoip.net/json/?callback=?', function(response){
        userData = response;

        // Uncomment this line to see what is returned:
        // console.log(response);
    });
}

Aunque el console.log viene después del load() llamada de función, en realidad se ejecuta antes de que se obtengan los datos.

10. Uso indebido de detectores de eventos

Digamos que desea escuchar los clics en un botón, pero solo mientras una casilla de verificación está marcada. Así es como un principiante podría hacerlo (usando jQuery):

var checkbox = $('input[type=checkbox]'),
    button = $('button');

// We want to listen for clicks only when the checkbox is marked.

checkbox.on('change', function(){

    // Is the checkbox checked?

    if(this.checked){

        // Listen for clicks on the button. 

        button.on('click', function(){

            // This alert is called more than once. Why?

            alert('Hello!');
        });
    }
});
<input type="checkbox" />

<button>Click me!</button>

<p>Click the checkbox a few times.</p>

Esto obviamente está mal. Idealmente, debe escuchar un evento solo una vez, como hicimos con el evento de cambio de la casilla de verificación. Llamando repetidamente al button.on('click' ..) da como resultado múltiples detectores de eventos que nunca se eliminan. Lo dejaré como ejercicio para que el lector haga que este ejemplo funcione :)

Conclusión

La mejor manera de evitar que ocurran errores como estos es usar JSHint. Algunos IDE ofrecen integración integrada con la herramienta, por lo que su código se verifica mientras escribe. Espero que hayas encontrado esta lista interesante. Si tienes alguna sugerencia, ¡tráela a la sección de comentarios!