Debugging - Josej2r/JavaScript_Algorithms_and_Data_Structures_Certification GitHub Wiki

Debugging

Introduction to the Debugging Challenges

La depuración es una herramienta valiosa y (desafortunadamente) necesaria para los programadores. Sigue la fase de prueba de verificar si su código funciona según lo previsto, y descubrirlo no. La depuración es el proceso de encontrar exactamente lo que no funciona y solucionarlo. Después de pasar tiempo creando un brillante bloque de código, es difícil darse cuenta de que puede tener errores. Estos problemas generalmente vienen en tres formas:

  1. errores de sintaxis que impiden que un programa se ejecute.

  2. errores de tiempo de ejecución cuando el código no se ejecuta o tiene un comportamiento inesperado.

  3. errores semánticos (o lógicos) cuando el código no hace lo que debe hacer.

Los editores de código modernos (y la experiencia) pueden ayudar a identificar errores de sintaxis. Los errores semánticos y de tiempo de ejecución son más difíciles de encontrar. Pueden hacer que su programa se bloquee, hacer que se ejecute para siempre o dar un resultado incorrecto. Piense en la depuración como tratando de entender por qué su código se comporta de la manera que lo hace. Ejemplo de un error de sintaxis, a menudo detectando por el editor código:

 funtcion willNotWork( 
  console.log("Yuck");
}
// "function" keyword is misspelled and there's a missing parenthesis

Aquí hay un ejemplo de un error de tiempo de ejecución, a menudo detectando mientra se ejecuta el el programa:

function loopy() {
  while(true) {
    console.log("Hello, world!");
  }
}
// Calling loopy starts an infinite loop, which may crash your browser

Ejemplo de un error semántico, a menudo detectado después de probar la salida del código:

function calcAreaOfRect(w, h) {
  return w + h; // This should be w * h
}
let myRectArea = calcAreaOfRect(2, 3);
// Correct syntax and the program executes, but this gives the wrong answer

La depuración es frustrante, pero ayuda a desarrollar (y seguir) un enfoque paso a paso para revisar su código. Esto significa verificar los valores intermedios y los tipos de variables para ver si son lo que deberían ser. Puede comenzar con un simple proceso de eliminación.

Por ejemplo, si la función A funciona y devuelve lo que se supone que debe hacer, entonces la función B puede tener el problema. O comience a verificar los valores en un bloque de código desde el medio para intentar reducir el espacio de búsqueda a la mitad. Un problema en un lugar indica un error en la primera mitad del código. Si no, es probable en el segundo.

Esta sección cubrirá un par de herramientas útiles para encontrar errores, y algunas de las formas comunes que toman. Afortunadamente, la depuración es una habilidad que se puede aprender que solo requiere un poco de paciencia y práctica para dominar.

Upcoming Lessons

Use the JavaScript Console to Check the Value of a Variable

Tanto Chrome como Firefox tienen excelentes consolas de JavaScript, también conocidas como DevTools, para depurar tu JavaScript.

Puedes encontrar herramientas para desarrolladores en el menú de Chrome o Consola web en el menú de FireFox. Si está utilizando un navegador diferente o un teléfono móvil, le recomendamos que cambie a Firefox o Chrome de escritorio.

El método console.log() que "imprime" la salida de lo que está entre paréntesis en la consola, probablemente se la herramienta de depuración más útil. Colocarlo en puntos estratégicos de su código puede mostrarle los valores intermedios de la variable. Es una buena idea tener una idea de cuál debería ser la salida antes de ver cuál es. Tener puntos de verificación para ver el estado de sus cálculos en todo su código ayudará a reducir dónde está el problema.

Aquí hay un ejemplo para imprimir 'Hello World' en la consola.

console.log('Hello world!');

Use el método console.log() para imprimir el valor de la variable a donde se indica en el código.

El código con la solución se encuentra aquí:Download

Understanding the Differences between the freeCodeCamp and Browser Console

Es posible que haya notado que algunos desafíos de JavaScript freeCodeCamp incluyen su propia consola. Esta consola se comporta de manera un poco diferente a la consola del navegador que utilizó en el último desafío.

En el siguiente desafío tiene como objetivo resaltar la diferencia principal entre la consola freeCodeCamp y la consola de su navegador.

Cuando ejecuta JavaScript ordinario, la consola del navegador mostrará sus declaraciones console.log() la cantidad exacta de veces que solicitó.

La consola de freeCodeCamp imprimirá sus declaraciones console.log() para cada prueba de ese desafío, así como una vez más para cualquier llamada de función que tenga en su código .

Esto se presta a un comportamiento interesante y podría tropezar al principio, porque un valor registrado que espera ver solo una vez puede imprimirse muchas más veces.

Si desea ver solo su salida única y no tener que preocuparse por ejecutar los ciclos de prueba, puede usar console.clear() y verificar la consola del navegador.

Primero, use console.clear() para borrar la consola del navegador. Después de eso, use console.log para registrar la variable de output.

El código con la solución se encuentra aquí:Download

Use typeof to Check the Type of a Variable

Puedes usar typeof para verificar la estructura de datos, o tipo, de una variable. Esto es útil en la depuración cuando se trabaja con múltiples tipos de datos. Si crees que estás agregando dos números, pero uno es en realidad una cadena, los resultados pueden ser inesperados. Los errores de tipo pueden acechar en los cálculos o las llamadas a funciones. Tenga en cuidado especialmente cuando está accediendo y trabajando con datos externos en forma de un objeto JSON (JavaScript Object Notation).

Aquí hay algunos ejemplos que usan typeof:

console.log(typeof ""); // outputs "string"
console.log(typeof 0); // outputs "number"
console.log(typeof []); // outputs "object"
console.log(typeof {}); // outputs "object"

JavaScript reconoce seis tipos de datos primitivos (inmutables): Booleano, Null, Undefined, String y Symbol (nuevo con ES6) y un tipo para elementos mutables: Object. Tenga en cuenta que en JavaScript, las matrices son técnicamente un tipo de objeto.

Agregue dos instrucciones console.log() para verificar el tipo de cada una de las dos variables seven y three en el código.

El código con la solución se encuentra aquí:Download

Catch Misspelled Variable and Function Names

Los métodos console.log() y typeof son las dos formas principales de verificar los valores intermedios y los tipos de salida del programa. Ahora es el momento de entrar en las formas comunes que toman los errores. Un problema de nivel de sintaxis con el que los escritores rápidos pueden compadecerse es el humilde error de ortografía.

Los caracteres transpuestros, faltantes o en mayúsculas en una variable o nombre de función harán que el navegador busque un objeto que no existe, y dejará en forma de un error de referencia. Los nombres de variables y funciones de JavaScript distinguen entre mayúsculas y minúsculas.

Solucione los dos errores de ortografía en el código para que funcione el cálculo de netWorkingCapital.

El código con la solución se encuentra aquí:Download

Catch Unclosed Parentheses, Brackets, Braces and Quotes

Otro error de sintaxis a tener en cuenta es que todos los paréntesis de apertura, corchetes, llaves y comillas tienen un par de cierre. Olvidar una pieza tiende a suceder cuando edita el código existente e inserta elemento con uno de los tipos de pares. Además tenga cuidado al anidar bloques de código en otros, como agregar una función de devolución de llamada como argumento para un método.

Una forma de evitar este error es que, tan pronto como se escriba el carácter de apertura, incluya inmediatamente la coincidencia de cierre, luego mueva el curso hacia atrás y continúe codificando. Afortunadamente, la mayoría de los editores de código modernos generan la segunda mitad del par automáticamente.

Solucione los dos errores de par en el código.

El código con la solución se encuentra aquí:Download

Catch Mixed Usage of Single and Double Quotes

JavaScript permite el uso de comillas simples (') y dobles (") para declarar una cadena. Decidir cuál usar generalmente se reduce a preferencias personales, con alguna excepciones.

Tener dos opciones es excelente cuando una cadena tiene contracciones u otro texto entre comillas. Solo tenga cuidado de no cerrar la cadena demasiado pronto, lo que causa un error de sintaxis.

Aquí hay algunos ejemplos de citas:

// These are correct:
const grouchoContraction = "I've had a perfectly wonderful evening, but this wasn't it.";
const quoteInString = "Groucho Marx once said 'Quote me as saying I was mis-quoted.'";
// This is incorrect:
const uhOhGroucho = 'I've had a perfectly wonderful evening, but this wasn't it.';

Por supuesto, está bien usar solo un estilo de comillas. Puede escapar las comillas de dentro de la cadena utilizando el carácter de escape de barra diagonal inversa ().:

// Correct use of same quotes:
const allSameQuotes = 'I\'ve had a perfectly wonderful evening, but this wasn\'t it.';

Arregle la cadena para que use comillas diferentes para el valor de href o escape de las comillas existentes. Mantenga las comillas dobles alrededor de toda la cadena.

El código con la solución se encuentra aquí:Download

Catch Use of Assignment Operator Instead of Equality Operator

Programas de ramificación, es decir, aquellos que hacen cosas diferentes si se cumplen ciertas condiciones, confían en las declaraciones if, else, else if en JavaScript. La condición a veces toma la forma de probar si un resultado es igual a un valor.

Esta lógica se habla como "sí x es igual a y, entonces...", que literalmente puede traducirse en códigos usando el operador de asignación =. Esto conduce a un flujo de control inesperado en su programa.

Como se cubrió en desafíos anteriores, el operador de asignación (=) en JavaScript asigna un valor a un nombre de variable. Y los operadores == y === verifican la igualdad y la igualdad estricta respectivamente.

El siguiente código asigna x para ser 2, que se evalúa como verdadero. Casi todos los valores en JavaScript se evalúan como verdaderos, excepto los que se como valores "falsy", false, 0, " ", NaN, undefined y null.

let x = 1;
let y = 2;
if (x = y) {
  // this code block will run for any value of y (unless y were originally set as a falsy)
} else {
  // this code block is what should run (but won't) in this example
}

Arregle la condición para que el programa ejecute la rama correcta y se asigne el valor apropiado al resultado.

El código con la solución se encuentra aquí:Download

Catch Missing Open and Closing Parenthesis After a Function Call

Cuando una función o método no toma ningún argumento, puede olvidar incluir los paréntesis de apertura y cierre (vacíos) al llamarlo. Muchas veces el resultado de una llamada de función se guarda en una variable para otro uso en su código. Este error se puede detectar registrando valores variables (o sus tipos) en la consola y viendo que uno está configurado como una referencia de función, en lugar del valor esperado que devuelve la función.

Las variables en el siguiente ejemplo son diferentes:

function myFunction() {
  return "You rock!";
}
let varOne = myFunction; // set to equal a function
let varTwo = myFunction(); // set to equal the string "You rock!"

Arregle el código para que el resultado variable se establezca en el valor devuelto al llamar a la función getNine.

El código con la solución se encuentra aquí:Download

Catch Arguments Passed in the Wrong Order When Calling a Function

Continuando con la discusión sobre las funciones de llamada, el siguiente error a tener en cuenta es cuando los argumentos de una función se suministran en el orden incorrecto. Si los argumentos son de diferentes tipos, como una función que espera una matriz y un entero, esto probablemente arrojará un error de tiempo de ejecución. Si los argumentos son del mismo tipo (todos los enteros, por ejemplo), entonces la lógica del código no tendrá sentido. Asegúrese de proporcionar todos los argumentos necesarios, en el orden correcto para evitar estos problemas.

La función raiseToPower eleva una base a un exponente. Desafortunadamente, no se llama correctamente, corrija el código para que el valor de la potencia sea el esperado 8.

El código con la solución se encuentra aquí:Download

Catch Off By One Errors When Using IndexingPassed

Apagados por un error ( a veces llamado OBOE) surgen cuando intentas apuntar a un índice específico de una cadena o matriz (para cortar o acceder a un segmento), o al recorrer sus índices. La indexación de JavaScript comienza en cero, no en uno, lo que significa que el último índice siempre es uno menos que la longitud del elemento. Si intenta acceder a un índice igual a la longitud, el programe puede arrojar un error de referencia "índice fuera de rango" o imprimir undefined.

Cuando utiliza métodos de cadena o matriz que toman rangos de índice como argumentos, ayuda leer la documentación y comprender si son inclusivos (el elemento en el índice dado es parte de lo que se devuelve) o no. Aquí hay algunos ejemplos de errores por uno:

let alphabet = "abcdefghijklmnopqrstuvwxyz";
let len = alphabet.length;
for (let i = 0; i <= len; i++) {
  // loops one too many times at the end
  console.log(alphabet[i]);
}
for (let j = 1; j < len; j++) {
  // loops one too few times and misses the first character at index 0
  console.log(alphabet[j]);
}
for (let k = 0; k < len; k++) {
  // Goldilocks approves - this is just right
  console.log(alphabet[k]);
}

Solucione los dos errores de indexación en la siguiente función para que todos los números del 1 al 5 se impriman en la consola.

El código con la solución se encuentra aquí:Download

Use Caution When Reinitializing Variables Inside a Loop

A veces es necesario guardar información, incrementar contadores o restablecer variables dentro de un ciclo. Un problema es cuando las variables deben reinicializarse y no, o viceversa. Esto es particularmente peligroso si accidentalmente restablece la variable que se está utilizando para la condición del terminal, causando un bucle infinito.

La impresión de valores de variables con cada ciclo de su ciclo mediante el uso de console.log() puede descubrir comportamientos defectuosos relacionados con el restablecimiento o no restablecer una variable.

Se supone que la siguiente función crea una matriz bidimiensional con m filas y n columnas de ceros. Desafortunadamente, no está produciendo la salida esperada porque la variable de fila no se está reinicializando (configurada en una matriz vacía) en el bucle externo. Arregle el código para que devuelva una matriz de ceros 3x2 correcta. que se ve como [0, 0], [0, 0], 0, 0.

El código con la solución se encuentra aquí:Download

Prevent Infinite Loops with a Valid Terminal Condition

El tema final es el temido bucle infinito. Los bucles son excelentes herramientas cuando necesita que su programa ejecute un bucle de código un cierto número de veces o hasta que se cumpla una condición, pero necesitan una condición terminal que finalice el bucle. Es problema que los bucles infinitos congelen o bloqueen el navegador y causen el caos general de ejecución del programa, que nadie quiere.

Hubo un ejemplo de un bucle infinito en la introducción de esta sección: no tenía una condición terminal para salir del bucle while dentro de loopy(). ¡No llame a esta función!.

function loopy() {
  while(true) {
    console.log("Hello, world!");
  }
}

El trabajo del programador es garantizar que la condición del terminal, que le dice al programa cuándo salir del código de bucle, se alcance finalmente. Un erro es aumentar o disminuir una variable de contador en la dirección incorrecta desde la condición del terminal. Otro está restableciendo accidentalmente un contador o variable de índice dentro del código de bucle, en lugar de aumentarlo o disminuirlo.

La función myFunc() contiene un bucle infinito porque la condición de terminar es !=4 nunca se evaluará como falsa (y romperá el bucle): incrementaré en 2 cada pasada y saltaré sobre 4 ya que es par para comenzar. Arregle el operador de comparación en la condicional terminal para que el bucle solo se ejecute por i menor o igual que 4.

El código con la solución se encuentra aquí:Download