11 trucos de JavaScript que no encontrarás en la mayoría de los tutoriales

Consejos útiles para escribir JavaScript más conciso y eficaz

Crédito de la imagen: Igor Miske / Unsplash

Cuando comencé a aprender JavaScript, hice una lista de todos los trucos para ahorrar tiempo que encontré en el código de otras personas, en sitios web de desafío de código y en cualquier otro lugar que no fuera los tutoriales que estaba usando.

He estado contribuyendo a esta lista desde entonces, y en este artículo, compartiré 11 consejos cuidadosamente seleccionados que me parecen particularmente inteligentes o útiles. Esta publicación está destinada a ser útil para principiantes, pero espero que incluso los desarrolladores intermedios de JavaScript encuentren algo nuevo en esta lista.

Si bien muchos de estos trucos son útiles en cualquier contexto, algunos de ellos pueden ser más adecuados para el golf de código que el código de nivel de producción, donde la claridad es a menudo más importante que la concisión; ¡Te dejaré ser el juez de eso!

Entonces, sin ningún orden en particular, aquí hay 11 formas ordenadas de escribir código más conciso y con mejor rendimiento.

1. Filtrar valores únicos

Matrices

El tipo de objeto Set se introdujo en ES6 y, junto con ..., el operador "spread", podemos usarlo para crear una nueva matriz con solo los valores únicos.

const array = [1, 1, 2, 3, 5, 5, 1]
const uniqueArray = [... nuevo conjunto (matriz)];
console.log (uniqueArray); // Resultado: [1, 2, 3, 5]

Antes de ES6, aislar valores únicos implicaría mucho más código que eso.

Este truco funciona para matrices que contienen tipos primitivos: indefinido, nulo, booleano, cadena y número. (Si tuviera una matriz que contiene objetos, funciones o matrices adicionales, ¡necesitaría un enfoque diferente!)

2. Evaluación de cortocircuito

Condicionales

El operador ternario es una forma rápida de escribir declaraciones condicionales simples (y a veces no tan simples), como estas:

x> 100? 'Por encima de 100': 'Por debajo de 100';
x> 100? (x> 200? 'Por encima de 200': 'Entre 100-200'): 'Por debajo de 100';

Pero a veces incluso el operador ternario es más complicado de lo necesario. En su lugar, podemos usar ‘y’ && y ‘o’ || operadores lógicos para evaluar ciertas expresiones de una manera aún más concisa. Esto a menudo se llama "cortocircuito" o "evaluación de cortocircuito".

Cómo funciona

Supongamos que queremos devolver solo una de dos o más opciones.

El uso de && devolverá el primer valor falso o "falso". Si cada operando se evalúa como verdadero, se devolverá la última expresión evaluada.

deja uno = 1, dos = 2, tres = 3;
console.log (uno y dos y tres); // Resultado: 3
console.log (0 && null); // Resultado: 0

Usando || devolverá el primer valor verdadero o "verdadero". Si cada operando se evalúa como falso, se devolverá la última expresión evaluada.

deja uno = 1, dos = 2, tres = 3;
console.log (uno || dos || tres); // Resultado: 1
console.log (0 || nulo); // Resultado: nulo

Ejemplo 1

Supongamos que queremos devolver la longitud de una variable, pero no sabemos el tipo de variable.

Podríamos usar una declaración if / else para verificar que foo es un tipo aceptable, pero esto podría ser bastante largo. La evaluación de cortocircuito nos permite hacer esto en su lugar:

return (foo || []). length;

Si la variable foo es verdadera, se devolverá. De lo contrario, se devolverá la longitud de la matriz vacía: 0.

Ejemplo 2

¿Alguna vez ha tenido problemas para acceder a una propiedad de objeto anidado? Es posible que no sepa si el objeto o una de las subpropiedades existe, y esto puede causar errores frustrantes.

Supongamos que queríamos acceder a una propiedad llamada datos dentro de this.state, pero los datos no están definidos hasta que nuestro programa haya devuelto con éxito una solicitud de recuperación.

Dependiendo de dónde lo usemos, llamar a this.state.data podría evitar que nuestra aplicación se ejecute. Para evitar esto, podríamos envolverlo en un condicional:

if (this.state.data) {
  devuelve this.state.data;
} más {
  devolver 'Obteniendo datos';
}

Pero eso parece bastante repetitivo. El operador "o" proporciona una solución más concisa:

return (this.state.data || 'Obteniendo datos');

No podemos refactorizar el código anterior para usar &&. La declaración 'Obteniendo datos' && this.state.data devolverá this.state.data si está indefinido o no. Esto se debe a que 'Obtener datos' es "verdadero", por lo que && siempre lo pasará por alto cuando aparezca en primer lugar.

Una nueva característica propuesta: encadenamiento opcional

Actualmente hay una propuesta para permitir el "encadenamiento opcional" al intentar devolver una propiedad en lo profundo de una estructura en forma de árbol. Según la propuesta, el símbolo del signo de interrogación? podría usarse para extraer una propiedad solo si no es nula.

Por ejemplo, podríamos refactorizar nuestro ejemplo anterior a this.state.data?. (), Por lo tanto, solo devolverá datos si no es nulo.

O, si nos preocupara principalmente si el estado se definió o no, podríamos devolver este. Estado? .Datos.

La propuesta se encuentra actualmente en la Etapa 1, como una característica experimental. Puede leer sobre esto aquí, y puede usarlo en su JavaScript ahora a través de Babel, agregando @ babel / plugin-offer-optional-chaining a su archivo .babelrc.

3. Convertir a booleano

TIPO DE CONVERSIÓN

Además de los valores booleanos regulares verdadero y falso, JavaScript también trata todos los demás valores como "verdadero" o "falso".

A menos que se defina lo contrario, todos los valores en JavaScript son "veraces" con la excepción de 0, "", nulo, indefinido, NaN y, por supuesto, falso, que son "falsos".

¡Podemos cambiar fácilmente entre verdadero y falso usando el operador negativo! , que también convertirá el tipo a "booleano".

const isTrue =! 0;
const isFalse =! 1;
const alsoFalse = !! 0;
console.log (isTrue); // Resultado: verdadero
console.log (typeof true); // Resultado: "booleano"

Este tipo de conversión de tipo puede ser útil en declaraciones condicionales, aunque la única razón por la que elegiría definir falso como! 1 es si estaba jugando al código golf!

4. Convertir a cadena

TIPO DE CONVERSIÓN

Para convertir rápidamente un número en una cadena, podemos usar el operador de concatenación + seguido de un conjunto vacío de comillas "".

const val = 1 + "";
console.log (val); // Resultado: "1"
console.log (typeof val); // Resultado: "cadena"

5. Convertir a número

TIPO DE CONVERSIÓN

Lo contrario se puede lograr rápidamente utilizando el operador de suma +.

let int = "15";
int = + int;
console.log (int); // Resultado: 15
console.log (typeof int); Resultado: "número"

Esto también se puede usar para convertir booleanos a números, como se muestra a continuación:

console.log (+ verdadero); // Regreso: 1
console.log (+ false); // Regreso: 0

Puede haber contextos donde el + se interpretará como el operador de concatenación en lugar del operador de suma. Cuando eso sucede (y desea devolver un número entero, no un flotante), puede usar dos tildes: ~~.

Una tilde, conocida como el "operador NOT bit a bit", es un operador equivalente a-n - 1. Entonces, por ejemplo, ~ 15 es igual a -16.

El uso de dos tildes en una fila niega efectivamente la operación, porque - (- n - 1) - 1 = n + 1 - 1 = n. En otras palabras, ~ - 16 es igual a 15.

const int = ~~ "15"
console.log (int); // Resultado: 15
console.log (typeof int); Resultado: "número"

Aunque no puedo pensar en muchos casos de uso, el operador NOT bit a bit también se puede usar en booleanos: ~ true = -2 y ~ false = -1.

6. Poderes rápidos

Operaciones

Desde ES7, ha sido posible utilizar el operador de exponenciación ** como abreviatura de potencias, que es más rápido que escribir Math.pow (2, 3). ¡Esto es sencillo, pero está en la lista porque no se han actualizado muchos tutoriales para incluir este operador!

console.log (2 ** 3); // Resultado: 8

Esto no debe confundirse con el símbolo ^, comúnmente usado para representar exponentes, pero que en JavaScript es el operador XOR bit a bit.

Antes de ES7, la taquigrafía solo existía para potencias con base 2, utilizando el operador de desplazamiento a la izquierda bit a bit <<:

// Las siguientes expresiones son equivalentes:
Math.pow (2, n);
2 << (n - 1);
2 ** n;

Por ejemplo, 2 << 3 = 16 es equivalente a 2 ** 4 = 16.

7. Flotación rápida a entero

OPERACIONES / CONVERSIÓN DE TIPO

Si desea convertir un flotante en un entero, puede usar Math.floor (), Math.ceil () o Math.round (). Pero también hay una forma más rápida de truncar un flotante a un entero utilizando |, el operador OR a nivel de bit.

console.log (23.9 | 0); // Resultado: 23
console.log (-23.9 | 0); // Resultado: -23

El comportamiento de | varía dependiendo de si se trata de números positivos o negativos, por lo que es mejor usar este acceso directo si está seguro.

Si n es positivo, n | 0 efectivamente redondea hacia abajo. Si n es negativo, efectivamente se redondea. Para decirlo con mayor precisión, esta operación elimina todo lo que viene después del punto decimal, truncando un flotante a un entero.

Puede obtener el mismo efecto de redondeo utilizando ~~, como anteriormente, y de hecho, cualquier operador bit a bit forzaría un flotador a un entero. Las razones por las que funcionan estas operaciones particulares es que, una vez forzado a un número entero, el valor no se modifica.

Eliminar dígitos finales

El operador OR bit a bit también se puede usar para eliminar cualquier cantidad de dígitos del final de un entero. Esto significa que no tenemos que usar un código como este para convertir entre tipos:

let str = "1553";
Number (str.substring (0, str.length - 1));

En cambio, el operador OR a nivel de bit nos permite escribir:

console.log (1553/10 | 0) // Resultado: 155
console.log (1553/100 | 0) // Resultado: 15
console.log (1553/1000 | 0) // Resultado: 1

8. Enlace automático en clases

Clases

Podemos usar la notación de flecha ES6 en los métodos de clase, y al hacerlo, el enlace está implícito. ¡Esto a menudo guardará varias líneas de código en nuestro constructor de clases, y podemos decir adiós a expresiones repetitivas como this.myMethod = this.myMethod.bind (this)!

import React, {Component} de React;
la aplicación de clase predeterminada de exportación extiende Compononent {
  constructor (accesorios) {
  super (accesorios);
  this.state = {};
  }
myMethod = () => {
    // ¡Este método está vinculado implícitamente!
  }
render () {
    regreso (
      <>
        
          {this.myMethod ()}         
           )   } };

9. Truncar una matriz

Matrices

Si desea eliminar valores del final de una matriz de forma destructiva, existen alternativas más rápidas que usar splice ().

Por ejemplo, si conoce el tamaño de su matriz original, puede redefinir su propiedad de longitud, así:

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array.length = 4;
console.log (matriz); // Resultado: [0, 1, 2, 3]

Esta es una solución particularmente concisa. Sin embargo, he encontrado que el tiempo de ejecución del método slice () es aún más rápido. Si la velocidad es su objetivo principal, considere usar algo como esto:

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array = array.slice (0, 4);
console.log (matriz); // Resultado: [0, 1, 2, 3]

10. Obtenga los últimos elementos en una matriz

Matrices

El método de matriz slice () puede tomar enteros negativos y, si se proporciona, tomará valores desde el final de la matriz en lugar de desde el principio.

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log (array.slice (-1)); // Resultado: [9]
console.log (array.slice (-2)); // Resultado: [8, 9]
console.log (array.slice (-3)); // Resultado: [7, 8, 9]

11. Formato de código JSON

JSON

Por último, es posible que haya utilizado JSON.stringify antes, pero ¿se dio cuenta de que también puede ayudarlo a sangrar su JSON?

El método stringify () toma dos parámetros opcionales: una función de reemplazo, que puede usar para filtrar el JSON que se muestra, y un valor de espacio.

El valor de espacio toma un número entero para la cantidad de espacios que desea o una cadena (como '\ t' para insertar pestañas), y puede hacer que sea mucho más fácil leer datos JSON recuperados.

console.log (JSON.stringify ({alpha: 'A', beta: 'B'}, null, '\ t'));
// Resultado:
// '{
// "alfa": A,
// "beta": B
//} '

En general, espero que haya encontrado estos consejos tan útiles como lo hice cuando los descubrí por primera vez.

¿Tienes algún truco de JavaScript propio? ¡Me encantaría leerlos en los comentarios a continuación!

12. [En desuso] Longitud de la matriz de caché en bucles

Bucles

En la versión original de este artículo, compartí un consejo sobre la longitud de la matriz de caché para bucles. Sin embargo, si se trata de un bucle de solo lectura, los motores JavaScript modernos se ocupan de esto en el momento de la compilación. Ya no es necesario a menos que cambie la longitud de la matriz (y, si ese es el caso, probablemente querrá que se vuelva a calcular con cada iteración de todos modos).

Gracias a varios comentaristas que señalaron esto. Si desea obtener más información, consulte esta pregunta en StackOverflow.

Para aquellos que estén interesados, solía haber algún incentivo de rendimiento para escribir para (let i = 0, len = array.length; i