Skip to content

Conceptos clave y fundamentales de JavaScript que todo programador debería conocer

JavaScript es uno de los lenguajes de programación más populares y utilizados en el mundo. Desde aplicaciones web hasta aplicaciones móviles, JavaScript es una herramienta imprescindible para los desarrolladores en todo el mundo. Sin embargo, aunque puede ser un lenguaje poderoso, puede resultar intimidante para aquellos que recién comienzan en el mundo de la programación.

En este artículo, vamos a explorar los conceptos clave y fundamentales de JavaScript que todo programador debería conocer. Desde la sintaxis básica hasta las características más avanzadas, te guiaremos a través de todo lo que necesitas saber para convertirte en un programador de JavaScript confiado y capaz.

Desarrollo moderno

Para comenzar a jugar con JS vamos a utilizar node.js + npm + vite.js.

Node.js es como el horno en una cocina, NPM es como los ingredientes que se usan para cocinar y Vite.js es como un libro de recetas que te ayuda a crear platos nuevos y emocionantes de manera rápida y fácil.

Node js

Node.js es un entorno de ejecución de JavaScript construido sobre el motor de JavaScript V8 de Google Chrome. Permite a los desarrolladores ejecutar código JavaScript en el lado del servidor, lo que significa que puede crear aplicaciones web completas utilizando solo JavaScript.

Node.js se utiliza para desarrollar aplicaciones de servidor, herramientas de línea de comandos, scripts y cualquier otro tipo de aplicación que requiera la ejecución de código JavaScript fuera del navegador web. Proporciona una plataforma para construir aplicaciones escalables y de alta velocidad utilizando un modelo de programación asincrónico y sin bloqueo que permite manejar múltiples solicitudes concurrentemente.

Node.js tiene una amplia variedad de bibliotecas y módulos disponibles a través de su sistema de gestión de paquetes npm, lo que hace que el desarrollo de aplicaciones sea más fácil y eficiente. Además, Node.js se ha convertido en una tecnología popular en el mundo del desarrollo web y ha sido adoptado por muchas empresas para desarrollar aplicaciones de alto rendimiento.

¿Qué es un módulo?

  • Un módulo no es nada más que una unidad de código organizado en archivos o directorios, la cual puede ser exportada con facilidad para poder reutilizarse en otras partes de la aplicación. fuente
  • External modules: Son, en esencia, los paquetes de terceros distribuidos a través de npm (aunque pueden provenir de otros repositorios). Estos paquetes se instalan como dependencias y, aunque aportan funcionalidad a la aplicación, no deben incluirse en el repositorio ya que no son parte de la misma.

npm

npm (Node Package Manager) es el administrador de paquetes para Node.js. Se utiliza para instalar, actualizar y administrar paquetes de código fuente de JavaScript para proyectos de Node.js.

npm proporciona acceso a una gran cantidad de paquetes de software de código abierto, como bibliotecas de terceros, frameworks y herramientas de línea de comandos, que los desarrolladores pueden utilizar en sus propios proyectos. Estos paquetes se encuentran en el registro público de npm y pueden ser descargados e instalados fácilmente utilizando la línea de comandos de npm.

npm también se utiliza para administrar las dependencias del proyecto. Cuando se crea un nuevo proyecto de Node.js, se genera automáticamente un archivo package.json que contiene una lista de dependencias del proyecto y sus versiones. npm se encarga de instalar todas estas dependencias y sus dependencias secundarias, lo que hace que el proceso de administración de dependencias sea mucho más fácil y eficiente.

Además, npm es muy popular en la comunidad de Node.js y se ha convertido en una herramienta esencial para el desarrollo de aplicaciones web en JavaScript.

package.json

package.json es un archivo utilizado en proyectos de Node.js para describir las dependencias, configuraciones y scripts necesarios para el proyecto. Contiene metadatos del proyecto, como el nombre, la versión, la descripción y la información del autor, así como una lista de dependencias y scripts que se utilizan en el proyecto.

El archivo package.json se encuentra en la raíz del proyecto y se crea automáticamente cuando se inicia un nuevo proyecto de Node.js utilizando el comando npm init o yarn init. Las dependencias del proyecto se agregan al archivo package.json utilizando los comandos npm install o yarn add, y los scripts personalizados se agregan a la sección "scripts" del archivo.

El archivo package.json también se utiliza para definir la versión de Node.js compatible con el proyecto, las licencias y las etiquetas para facilitar la búsqueda de paquetes en el registro de npm. En resumen, package.json es un archivo importante para cualquier proyecto de Node.js ya que define las dependencias y configuraciones necesarias para el proyecto.

Vite JS (Next Generation Frontend Tooling)

Vite.js es un framework de desarrollo web para construir aplicaciones modernas basadas en JavaScript. Fue creado por Evan You, el creador de Vue.js, y está diseñado para ser muy rápido y eficiente en el desarrollo y construcción de aplicaciones web.

La principal característica de Vite.js es su capacidad para proporcionar una experiencia de desarrollo muy rápida y en tiempo real. Utiliza un servidor de desarrollo que utiliza la funcionalidad nativa del navegador para cargar y actualizar rápidamente los archivos de la aplicación, lo que significa que los cambios se pueden ver en el navegador sin necesidad de reiniciar o recargar la página.

Además, Vite.js es muy flexible y se puede utilizar con una variedad de herramientas y marcos de JavaScript, como React, Vue.js, Angular, etc. También proporciona una gran cantidad de plugins y características, como la integración con TypeScript, el soporte para HMR (Hot Module Replacement) y la optimización del rendimiento, lo que lo convierte en una opción popular para el desarrollo de aplicaciones web modernas.

Snippets (opcional)

clg -> console.log()
nfn -> const first = (second) => { third }
anfn -> (first) => { second }
ednf -> export default function first(second) { third }

Const vs Let (ES6)

Las variables let y const introducidas en ES6 (ECMAScript 2015) tienen un alcance de bloque, lo que significa que solo son accesibles dentro del bloque donde se declaran. Esto hace que sea más fácil escribir código seguro, fácil de entender y mantener.

En JavaScript, let y const son formas de declarar variables, pero tienen algunas diferencias clave:

  1. Asignación de valores:: La variable declarada con const no puede ser reasignada a un nuevo valor después de su inicialización, mientras que la variable declarada con let sí puede ser reasignada a un nuevo valor en cualquier momento.
js
let contador = 0; // cambia a const y visualiza el error
contador = contador + 1;
console.log(contador);

¿const inmutable?

La declaración de una constante crea una referencia de sólo lectura. No significa que el valor que tiene sea inmutable, sino que el identificador de variable no puede ser reasignado, por lo tanto, en el caso de que la asignación a la constante sea un objeto, el objeto sí que puede ser alterado. Fuente

  1. Alcance: tanto let como const tienen un alcance de bloque, lo que significa que solo están disponibles dentro del bloque de código en el que se declaran, y no fuera de él.
js
let contador = 0;

if (true) {
  let incrementador = 2;
  contador = contador + incrementador; // 2
  contador = contador + incrementador; // 4
}

console.log(incrementador); // Uncaught ReferenceError: incrementador is not defined
js
let contador = 0;
let incrementador = 1;

if (true) {
  let incrementador = 2;
  contador = contador + incrementador; // 2
  contador = contador + incrementador; // 4
}

console.log(incrementador); // 1
  1. Inicialización: cuando se declara una variable con let, no es necesario inicializarla con un valor. La variable se crea con un valor indefinido hasta que se le asigna un valor más tarde. En cambio, las variables declaradas con const deben ser inicializadas con un valor en el momento de su declaración, de lo contrario, el código arrojará un error.
js
let contador = 0;
let incrementador; // undefined

if (true) {
  incrementador = 2;
  contador = contador + incrementador; // 2
  contador = contador + incrementador; // 4
}

console.log(incrementador); // 2

var (antes de ES6)

La razón por la que se recomienda no utilizar la palabra clave var en JavaScript es porque tiene un alcance de función o global, lo que significa que las variables definidas con var pueden ser accesibles fuera del bloque donde se declaran.

Esto puede conducir a errores difíciles de detectar y problemas de mantenimiento en el código, especialmente en proyectos más grandes y complejos. Por ejemplo, si se define una variable con var dentro de una función y se utiliza fuera de ella, puede sobrescribir valores de variables existentes o incluso crear variables globales involuntariamente.

js
console.log(incrementador); // undefined
var incrementador;
js
if (true) {
  var decrementador = 3;
}
console.log(decrementador); // 3

Object literals

En JavaScript, los objetos literales (Object literals) son una forma de crear un objeto de manera más concisa y legible en el código. Cuentan con propiedades y valores.

La sintaxis básica de un objeto literal es la siguiente:

js
const objeto = {
  propiedad1: valor1,
  propiedad2: valor2,
  propiedad3: valor3,
};

Cada propiedad se especifica como un par clave-valor, separado por dos puntos (😃, y cada propiedad separada por una coma. La clave es una cadena que actúa como identificador de la propiedad, mientras que el valor puede ser cualquier valor de JavaScript, incluyendo otros objetos, funciones, arreglos, etc.

js
const persona = {
  nombre: "bluuweb",
  apellido: "Suscríbete",
  edad: 30,
  hobbies: ["surfear", "programar", "correr"],
  saludar: function () {
    console.log("Hola, soy " + this.nombre);
  },
};
js
const persona = {
  nombre: "bluuweb",
  apellido: "Suscríbete",
  edad: 30,
  hobbies: ["surfear", "programar", "correr"],
  saludar: function () {
    console.log("Hola, soy " + this.nombre);
  },
};

console.log(persona.nombre);
console.log(persona.apellido);
console.log(persona.edad);
console.log(persona.hobbies);
console.log(persona.hobbies[0]);
persona.saludar();

Optional chaining operator

el operador de encadenamiento opcional permite acceder a las propiedades de objetos de manera segura sin tener que preocuparse por si la propiedad existe o no. Si la propiedad no existe, el operador simplemente devuelve undefined.

js
const persona = {
  nombre: "Bluuweb",
  apellido: "Suscríbete",
  direccion: {
    calle: "Calle Falsa",
    ciudad: "Ciudad Ficticia",
    codigoPostal: "12345",
  },
};

Si queremos acceder a la propiedad codigoPostal dentro de la propiedad direccion, normalmente lo haríamos así:

js
const codigoPostal = persona.direccion.codigoPostal;
console.log(codigoPostal); // Output: 12345

Sin embargo, si la propiedad direccion no existe en el objeto persona, obtendremos un error al intentar acceder a la propiedad codigoPostal. Para evitar esto, podemos utilizar el operador de encadenamiento opcional para verificar si la propiedad direccion existe antes de acceder a la propiedad codigoPostal:

js
const codigoPostal = persona.direccion?.codigoPostal;
console.log(codigoPostal); // Output: 12345

En este caso, si la propiedad direccion no existe en el objeto persona, el valor de codigoPostal será undefined, pero no se producirá un error.

js
let persona;
console.log(persona?.direccion?.calle);

Desctructuring

Es una característica introducida en ECMAScript 6 que permite a los programadores desempaquetar valores de objetos o arreglos en variables individuales, de forma más concisa y legible. El destructuring se utiliza a menudo en conjunto con la sintaxis de literales de objeto y arreglos.

El destructuring de objeto permite extraer los valores de propiedades de un objeto y asignarlos a variables individuales. Por ejemplo, si tenemos un objeto persona con dos propiedades, nombre y edad, podemos extraer estos valores en variables individuales de la siguiente manera:

js
const persona = {
  nombre: "bluuweb",
  apellido: "Suscríbete",
};

const { nombre, apellido } = persona;

console.log(nombre); // bluuweb
console.log(apellido); // Suscríbete

El destructuring de arreglos es similar, pero en lugar de extraer los valores de las propiedades de un objeto, extrae los valores de los elementos de un arreglo. Por ejemplo, si tenemos un arreglo de frutas, podemos extraer los valores de los dos primeros elementos en variables individuales de la siguiente manera:

js
const frutas = ["manzana", "naranja", "banana"];

const [fruta1, fruta2] = frutas;

console.log(fruta1); // manzana
console.log(fruta2); // naranja

El destructuring es una característica muy útil de JavaScript que permite descomponer valores complejos en valores más simples, lo que hace que el código sea más fácil de leer y escribir.

Functions

En JavaScript, las funciones son bloques de código que pueden ser llamados y ejecutados varias veces en diferentes partes de un programa. Son una parte fundamental del lenguaje y se utilizan para encapsular lógica y reutilizarla en diferentes partes del código.

Las funciones en JavaScript pueden ser definidas de varias maneras, incluyendo como funciones con nombre, funciones anónimas, funciones flecha, entre otras. Las funciones también pueden aceptar parámetros, que son valores que se pasan a la función cuando se llama, y pueden devolver valores de salida.

Las funciones también pueden ser almacenadas en variables, pasadas como argumentos a otras funciones, y ser devueltas como valores de otras funciones. Esto se conoce como programación funcional y es una técnica muy poderosa para escribir código modular, reutilizable y fácil de mantener.

Un ejemplo de una función en JavaScript podría ser una función que acepta dos parámetros, realiza una operación aritmética con ellos, y devuelve el resultado:

js
function sumar(a, b) {
  return a + b;
}

console.log(sumar(2, 3)); // Imprime 5 en la consola

En este ejemplo, la función sumar acepta dos parámetros a y b, realiza la operación a + b y devuelve el resultado usando la sentencia return. La función es llamada con los argumentos 2 y 3 y el resultado 5 se imprime en la consola usando console.log().

Arrow Functions

Las "arrow functions" son una característica introducida en ECMAScript 6 que permiten a los programadores definir funciones de manera más concisa y legible utilizando una sintaxis simplificada

Por ejemplo, si queremos definir una función que tome dos parámetros y devuelva su suma, podemos hacerlo utilizando una arrow function de la siguiente manera:

js
const sumar = (a, b) => {
  return a + b;
};

console.log(sumar(2, 3)); // 5

Una de las principales ventajas de las arrow functions es su sintaxis más concisa y legible, que puede ahorrar tiempo y esfuerzo al escribir código.

También hay una ligera variación en la semántica de la palabra clave this, que hace que las arrow functions sean más convenientes para ciertos casos de uso, como las devoluciones de llamada.

this

En realidad, en las arrow functions sí existe la palabra clave this, pero su semántica es ligeramente diferente de la de las funciones regulares.

En las funciones regulares, el valor de this depende de cómo se llama la función, lo que puede llevar a errores y confusión en ciertos casos. En cambio, en las arrow functions, el valor de this está determinado por el contexto léxico en el que se define la función.

En otras palabras, cuando se utiliza this dentro de una arrow function, se hace referencia al valor de this en el contexto que rodea a la función, no al valor de this en la función en sí misma. Esto significa que las arrow functions son particularmente útiles en situaciones donde se necesita conservar el valor de this de un objeto padre, por ejemplo, en los métodos de los objetos.

Por ejemplo, supongamos que tenemos un objeto persona con un método saludar que utiliza una arrow function para imprimir un saludo con el nombre de la persona:

js
const persona = {
  nombre: "bluuweb",
  saludar: function () {
    setTimeout(() => {
      console.log("Hola, mi nombre es " + this.nombre);
    }, 1000);
  },
};

persona.saludar(); // Hola, mi nombre es bluuweb

En este ejemplo, el método saludar utiliza una arrow function en la función setTimeout para imprimir un saludo con el nombre de la persona. La arrow function utiliza this.nombre para acceder al nombre de la persona, pero en lugar de referirse a setTimeout como lo haría una función regular, hace referencia al valor de this en el contexto léxico del objeto persona.

En resumen, aunque las arrow functions sí tienen la palabra clave this, su semántica es ligeramente diferente a la de las funciones regulares, lo que las hace especialmente útiles en situaciones donde se necesita conservar el valor de this de un objeto padre.

Array Methods

Los métodos de arreglo, también conocidos como "Array methods" en inglés, son funciones integradas de JavaScript que se pueden utilizar para manipular y transformar arreglos de datos. Estos métodos hacen que trabajar con arreglos en JavaScript sea más fácil y eficiente.

Aquí hay algunos ejemplos de los métodos de arreglo más importantes en JavaScript:

  1. map(): crea un nuevo arreglo a partir de un arreglo existente aplicando una función a cada elemento.
  2. filter(): crea un nuevo arreglo a partir de un arreglo existente que contiene solo los elementos que cumplen con una condición específica.
  3. reduce(): ejecuta una función en cada elemento del arreglo para reducir el arreglo a un solo valor.
  4. forEach(): ejecuta una función en cada elemento del arreglo, pero no crea un nuevo arreglo.
  5. sort(): ordena los elementos del arreglo.
  6. slice(): crea un nuevo arreglo a partir de un subconjunto de elementos seleccionados.
  7. concat(): une dos o más arreglos en un solo arreglo.
  8. indexOf(): busca el índice de un elemento específico en el arreglo.
  9. push(): agrega un elemento al final del arreglo.
  10. pop(): elimina el último elemento del arreglo.

Estos son solo algunos de los métodos de arreglo más importantes en JavaScript. Cada uno de ellos tiene su propio propósito y se puede utilizar en diferentes situaciones según las necesidades del programador. Además, JavaScript también tiene otros métodos de arreglo, como shift(), unshift(), splice(), includes(), find(), every(), some(), entre otros.

Spread & Rest Operator

El "spread operator" y el "rest operator" son dos características introducidas en ECMAScript 6 que permiten a los programadores manipular arreglos y objetos de manera más eficiente y flexible.

El spread operator es una sintaxis que permite expandir un objeto iterable, como un arreglo o una cadena, en múltiples elementos. Se denota con tres puntos (...) seguidos del objeto iterable que se desea expandir. Por ejemplo, si tenemos dos arreglos a y b, podemos combinarlos en un solo arreglo utilizando el spread operator de la siguiente manera:

js
const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [...a, ...b];

console.log(c); // [1, 2, 3, 4, 5, 6]

En este ejemplo, el operador spread ... se utiliza para expandir los arreglos a y b en elementos individuales, que se combinan en un solo arreglo c.

El rest operator, por otro lado, es una sintaxis que permite agrupar múltiples elementos en un objeto iterable, como un arreglo. También se denota con tres puntos ..., pero esta vez se utiliza en el lado izquierdo de una asignación para capturar los elementos sobrantes. Por ejemplo, si tenemos un arreglo de tres elementos a y queremos asignar los dos primeros elementos a dos variables individuales y el resto a otro arreglo, podemos hacerlo utilizando el rest operator de la siguiente manera:

js
const a = [1, 2, 3];
const [x, y, ...rest] = a;

console.log(x); // 1
console.log(y); // 2
console.log(rest); // [3]

En este ejemplo, el operador rest ... se utiliza para capturar el tercer elemento del arreglo a en la variable rest.

En resumen, el spread operator se utiliza para expandir un objeto iterable en múltiples elementos, mientras que el rest operator se utiliza para agrupar múltiples elementos en un objeto iterable. Ambas características son útiles para manipular arreglos y objetos de manera más eficiente y flexible en JavaScript.

Promises

Las Promises en JavaScript son un patrón para manejar operaciones asíncronas. Proporcionan una forma estructurada y fácil de leer para trabajar con código asíncrono, evitando el callback hell.

Una Promise representa un valor que puede estar disponible en el futuro, pero el cálculo de ese valor puede llevar algún tiempo. La idea detrás de las Promises es que el código que las utiliza pueda continuar ejecutándose mientras se espera a que se resuelva la Promise.

Las Promises tienen tres estados:

  • Pending (pendiente): el estado inicial, es decir, la Promise aún no se ha resuelto ni se ha rechazado.
  • Resolve (cumplida): la operación asíncrona se completó con éxito y la Promise ha sido resuelta con un valor.
  • Rejected (rechazada): la operación asíncrona no se completó con éxito y la Promise ha sido rechazada con una razón de rechazo.

Para crear una Promise, se utiliza la sintaxis:

js
const miPromise = new Promise((resolve, reject) => {
  // Hacer algo asíncrono...
  if (/* Operación asíncrona exitosa */) {
    resolve(resultado);
  } else {
    reject(error);
  }
});

La función que se pasa a la Promise como argumento toma dos parámetros: resolve y reject. resolve se llama cuando la operación asíncrona se completa con éxito y se devuelve el valor deseado. reject se llama cuando la operación asíncrona falla y se devuelve un error.

Una vez que se ha creado una Promise, se puede encadenar con then y catch para manejar la respuesta de la Promise:

js
miPromise
  .then((resultado) => {
    // Hacer algo con el resultado...
  })
  .catch((error) => {
    // Manejar el error...
  });

then se llama cuando la Promise se resuelve con éxito y se pasa el resultado de la Promise como argumento. catch se llama cuando la Promise es rechazada y se pasa el error como argumento.

En resumen, las Promises son un patrón para manejar operaciones asíncronas en JavaScript que proporciona una forma estructurada y fácil de leer para trabajar con código asíncrono y evitar el callback hell. Las Promises tienen tres estados: pendiente, cumplida y rechazada, y se pueden encadenar con then y catch para manejar la respuesta de la Promise.

Async await

Async/await es una función de JavaScript que se utiliza para manejar código asíncrono de una manera más legible y estructurada.

La palabra clave async se utiliza para definir una función como asíncrona, lo que significa que la función devolverá una Promise. Dentro de una función async, se puede utilizar la palabra clave await para esperar la resolución de una Promise antes de continuar con el siguiente bloque de código.

js
async function getDatos() {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

getDatos();

En este ejemplo, la función getDatos es una función asíncrona que utiliza await para esperar la respuesta de la API. La función fetch devuelve una Promise que resuelve en un objeto Response. Para obtener los datos de la respuesta, se utiliza await para esperar a que la respuesta se resuelva y luego se utiliza el método json para obtener los datos en formato JSON.

El bloque try/catch se utiliza para capturar cualquier error que pueda ocurrir durante la llamada a la API. Si se produce un error, se muestra el error en la consola.

Por último, se llama a la función getDatos para obtener los datos de la API y mostrarlos en la consola.

Modules (import & export)

import y export son dos declaraciones de JavaScript que se utilizan para importar y exportar módulos en el código.

import se utiliza para importar un módulo. Permite importar variables, funciones, clases, etc., desde un módulo externo en otro archivo JavaScript. Por ejemplo:

js
import { miFuncion } from "./miModulo.js";

En este ejemplo, estamos importando la función miFuncion desde el módulo miModulo.js.

Por otro lado, export se utiliza para exportar variables, funciones, clases, etc., desde un módulo para que puedan ser utilizados en otro archivo JavaScript. Por ejemplo:

js
export function miFuncion() {
  console.log("Hola desde miFuncion");
}

En este ejemplo, estamos exportando la función miFuncion para que pueda ser utilizada en otros archivos JavaScript.

Hay diferentes maneras de utilizar export. También se puede utilizar export default para exportar un valor predeterminado desde un módulo, como una función o una clase. Por ejemplo:

js
export default function miFuncion() {
  console.log("Hola desde miFuncion");
}

En este ejemplo, estamos exportando la función miFuncion como el valor predeterminado del módulo.

En resumen, import y export son declaraciones de JavaScript que se utilizan para importar y exportar módulos en el código. import se utiliza para importar variables, funciones, clases, etc., desde un módulo externo en otro archivo JavaScript. export se utiliza para exportar variables, funciones, clases, etc., desde un módulo para que puedan ser utilizados en otro archivo JavaScript.

Operador ternario

El operador ternario es un operador condicional en JavaScript que se utiliza para evaluar una expresión y devolver un valor basado en si la expresión es verdadera o falsa. El operador ternario tiene la siguiente sintaxis:

js
condición ? valorSiVerdadero : valorSiFalso;

La condición es una expresión que se evalúa en true o false, valorSiVerdadero es el valor que se devuelve si la condición es verdadera, y valorSiFalso es el valor que se devuelve si la condición es falsa.

Por ejemplo, considera el siguiente código que utiliza un operador ternario para asignar un valor a la variable esMayor:

js
const edad = 18;
const esMayor = edad >= 18 ? "" : "No";
console.log(esMayor); // Output: Sí

En este caso, la condición edad >= 18 se evalúa como verdadera, por lo que la variable esMayor se establece en 'Sí'.

Podemos escribir el mismo código utilizando una declaración if-else en lugar de un operador ternario:

js
const edad = 18;
let esMayor;

if (edad >= 18) {
  esMayor = "";
} else {
  esMayor = "No";
}

console.log(esMayor); // Output: Sí

Sin embargo, el operador ternario puede ser más conciso y fácil de leer en algunos casos, especialmente cuando se trata de asignar valores simples a una variable basada en una condición.

operadores lógicos && y ||

los operadores lógicos && y || también son operadores condicionales en JavaScript y se utilizan para evaluar expresiones y devolver un valor basado en si la expresión es verdadera o falsa.

El operador && devuelve el primer valor falso o el último valor si todos los valores son verdaderos. Por ejemplo:

js
const resultado = true && 5 && "hola" && false;
console.log(resultado); // Output: false

En este caso, la expresión true && 5 && 'hola' && false se evalúa como falsa en el último valor (false), por lo que la variable resultado se establece en false.

Por otro lado, el operador || devuelve el primer valor verdadero o el último valor si todos los valores son falsos. Por ejemplo:

js
const resultado = false || 0 || "" || null || "hola";
console.log(resultado); // Output: hola

En este caso, la expresión false || 0 || '' || null || 'hola' se evalúa como verdadera en el último valor ('hola'), por lo que la variable resultado se establece en 'hola'.

Estos operadores se utilizan comúnmente en combinación con expresiones condicionales y otras técnicas de control de flujo en JavaScript.

template literals

Los template literals son una característica introducida en ES6 (ECMAScript 2015) que permite incluir expresiones interpoladas en cadenas de texto. Permiten una sintaxis más sencilla y legible para construir cadenas de texto dinámicas en JavaScript.

La sintaxis de los template literals se basa en el uso de comillas invertidas (backticks) en lugar de comillas simples o dobles para definir la cadena de texto. Además, se pueden incluir expresiones dinámicas dentro de la cadena de texto utilizando el ${} para encerrar la expresión.

Por ejemplo, considera el siguiente código:

js
const nombre = "Juan";
const edad = 30;
console.log(`Mi nombre es ${nombre} y tengo ${edad} años.`);

En este caso, el template literal se define utilizando comillas invertidas y se incluyen las variables nombre y edad dentro de la cadena de texto utilizando la sintaxis ${}. La salida en la consola sería:

Mi nombre es Juan y tengo 30 años.

Los template literals también permiten la escritura de cadenas de texto en múltiples líneas sin la necesidad de utilizar caracteres de escape como \n. Por ejemplo:

js
const texto = `
Esto es un ejemplo de
cadena de texto en
varias líneas.
`;
console.log(texto);

En este caso, la variable texto contiene una cadena de texto con saltos de línea reales, lo que resulta en la siguiente salida en la consola:

Esto es un ejemplo de
cadena de texto en
varias líneas.

Los template literals son una característica útil en JavaScript que hace que la construcción de cadenas de texto dinámicas sea más fácil y legible.

Dentro de ${}, se pueden incluir cualquier expresión JavaScript válida, siempre y cuando el resultado de la expresión sea una cadena de texto o pueda convertirse en una cadena de texto.

Sin embargo, es importante tener en cuenta que no se pueden incluir declaraciones de función, operadores de asignación o cualquier otra sintaxis que no pueda evaluarse como una expresión.

Por ejemplo, no se puede incluir una declaración de función dentro de ${}, ya que una declaración de función no es una expresión. En su lugar, se puede utilizar una función anónima o una arrow function como una expresión.

js
// Esto no funcionará:
const texto = `Mi nombre es ${function () {
  return "Juan";
}}.`;

// Esto funcionará:
const texto = `Mi nombre es ${() => "Juan"}.`;

En general, se puede incluir cualquier expresión que se pueda evaluar en JavaScript dentro de ${}, pero es importante tener en cuenta las limitaciones mencionadas anteriormente.

evaluar una expresión

Cuando se habla de "evaluar una expresión" en programación, se refiere al proceso de resolver y obtener un valor a partir de una combinación de operandos y operadores.

En JavaScript, una expresión es cualquier combinación de valores, variables, operadores y funciones que se puedan evaluar en un valor. Por ejemplo, las siguientes son expresiones válidas en JavaScript:

js
5 + 3;
nombreDeVariable;
("texto de ejemplo");
miFuncion(parametro1, parametro2);

Cuando se utiliza el operador ${} dentro de un template literal, lo que se espera es que se incluya una expresión válida de JavaScript que se pueda evaluar y cuyo resultado sea una cadena de texto.

Por ejemplo, en la siguiente línea de código:

js
const nombre = "Juan";
console.log(`Hola, mi nombre es ${nombre}.`);

La expresión ${nombre} se evalúa en el valor de la variable nombre, que es la cadena de texto "Juan". El resultado final es la cadena de texto "Hola, mi nombre es Juan.".

En resumen, una expresión en JavaScript es una combinación de valores, variables, operadores y funciones que se pueden evaluar en un valor. Cuando se utiliza el operador ${} dentro de un template literal, se espera que se incluya una expresión válida que se pueda evaluar y cuyo resultado sea una cadena de texto.

if?

Un if no se puede utilizar dentro de ${} en un template literal porque el if es una estructura de control y no una expresión. El if no devuelve un valor que se pueda evaluar o concatenar dentro de una cadena de texto.

En su lugar, se puede utilizar el operador ternario ? como una expresión dentro de ${} para evaluar una condición y devolver un valor en función del resultado de la condición. Por ejemplo:

js
const edad = 25;
console.log(`Tienes ${edad >= 18 ? "mayor de edad" : "menor de edad"}.`);

En este caso, la expresión ${edad >= 18 ? 'mayor de edad' : 'menor de edad'} evalúa la condición edad >= 18, y si la condición es verdadera devuelve la cadena de texto "mayor de edad", y si es falsa devuelve la cadena de texto "menor de edad". El resultado final es la cadena de texto "Tienes mayor de edad.".