Saltearse al contenido

Introducción a Javascript

JavaScript es un lenguaje de programación de alto nivel, interpretado y orientado a objetos. Fue creado originalmente para agregar interactividad y dinamismo a las páginas web, pero hoy en día se utiliza en una amplia variedad de aplicaciones, desde el desarrollo web hasta la creación de aplicaciones móviles y de escritorio.

Una de sus principales características es la capacidad para interactuar con el HTML y el CSS, permitiendo modificar y manipular elementos de la página de forma dinámica. Esto significa que podemos realizar cambios en tiempo real, responder a eventos como clics de botones o desplazamientos del mouse, y actualizar el contenido de la página sin tener que recargarla.

Además de ser un lenguaje versátil para el desarrollo web, JavaScript también cuenta con una amplia gama de librerías y frameworks que facilitan la creación de aplicaciones complejas. Algunos ejemplos populares incluyen Angular, Vue.js y, particularmente, React, el cual estudiaremos en esta asignatura.

JavaScript es un lenguaje interpretado, lo que significa que no necesita ser compilado antes de su ejecución. Esto permite un desarrollo rápido y ágil, ya que los cambios en el código pueden verse inmediatamente reflejados en la aplicación.

Por último, debemos destacar el hecho de que este intérprete se encuentra integrado en la mayoría de los navegadores web modernos, lo que significa que no es necesario instalar ningún software adicional para comenzar a programar en JavaScript. Todo lo que necesitas es un editor de texto y un navegador web para empezar a escribir y probar tu código, aunque algunos editores de código como Visual Studio Code o Atom ofrecen funcionalidades adicionales que facilitan el desarrollo en este lenguaje.

Sintaxis

Como cualquier lenguaje de programación, JavaScript tiene una serie de reglas y convenciones que debemos seguir para que nuestro código sea válido y funcione correctamente. A continuación, veremos algunos aspectos básicos de su sintaxis.

Variables

En JavaScript, podemos declarar variables utilizando las palabras clave var y let. Estas palabras clave tienen algunas diferencias en cuanto a su alcance y mutabilidad:

  • var: antes de la introducción de let en JavaScript ES6 - 2015, var era la única forma de declarar variables. Sin embargo, var tiene un alcance de función o alcance global, lo que significa que una variable declarada con var está disponible en toda la función en la que se declara y, si se declara en el ámbito global, está disponible en todo el script. Por supuesto, como toda variable, puede ser reasignada. Por ejemplo:

    1
    var name = "Juan";
    2
    name = "Pedro"; // Reasignación válida
  • let: tiene un alcance de bloque, lo que significa que una variable declarada con let está disponible sólo dentro del bloque en el que se declara, ya sea dentro de un bucle for, una estructura if o la definición de una función. Además, let permite la reasignación de valor. Por ejemplo:

1
let edad = 25;
2
edad = 30; // Reasignación válida

Constantes

En algunas ocasiones, necesitamos declarar variables cuyo valor no cambiará después de su asignación inicial, las cuales se conocen como constantes.

Para esto, debemos utilizar la palabra clave const, introducida en ES6 - 2015 al igual que let. Veremos que comparte algunas características con let, como el alcance de bloque, pero con la diferencia de que no permite la reasignación de valor. Por ejemplo:

1
const PI = 3.1416;
2
PI = 3.14; // Esto daría un error, ya que no se puede reasignar una constante.

Tipos de datos

JavaScript es un lenguaje de tipado dinámico, lo que significa que no es necesario especificar el tipo de dato al declarar una variable. El tipo de dato se determina automáticamente en tiempo de ejecución según el valor asignado a la variable.

No obstante, podemos distinguir algunos tipos de datos relevantes:

  • Números: representan valores numéricos, ya sean enteros o decimales. Para declarar un número de punto flotante, se utiliza el punto (.) como separador decimal.

    1
    let edad = 25;
    2
    let precio = 9.99;
  • Cadenas de texto: representan secuencias de caracteres y se utilizan para almacenar texto. Las cadenas se pueden declarar utilizando comillas simples (') o dobles (").

    1
    let nombre = "Juan";
    2
    let mensaje = 'Hola, ¿cómo estás?';
  • Booleanos: representan valores de verdadero o falso. Son útiles en expresiones condicionales y en la toma de decisiones. Los valores booleanos son true y false.

    1
    let esMayor = true;
    2
    let esMenor = false;
  • Arreglos: representan colecciones homogéneas de elementos ordenados secuencialmente. Los elementos de un arreglo se almacenan en posiciones numéricas llamadas índices, comenzando desde 0. Se declaran utilizando corchetes ([]) y separando los elementos con comas (,).

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let colores = ["rojo", "verde", "azul"];
  • null y undefined: null se utiliza para indicar la ausencia de valor de manera intencional, mientras que undefined se utiliza para indicar que una variable no tiene un valor asignado por defecto, ya sea porque no se ha inicializado o porque se ha eliminado su valor.

    1
    let valor1 = null; // Se indica que la variable no tiene valor intencionalmente (null)
    2
    let valor2; // Variable no inicializada (undefined)

Por último, podemos destacar el tipo de dato object, que analizaremos con más detalle más adelante.

Operadores

En JavaScript, existen diferentes tipos de operadores que se utilizan para realizar operaciones y manipulaciones en los valores y variables.

  • Operadores aritméticos: se utilizan para realizar operaciones matemáticas básicas, como suma, resta, multiplicación, división y módulo (resto de la división).

    1
    let suma = 5 + 3; // 8
    2
    let resta = 10 - 2; // 8
    3
    let multiplicacion = 4 * 6; // 24
    4
    let division = 15 / 3; // 5
    5
    let modulo = 10 % 3; // 1 (resto de la división de 10 entre 3)
  • Operadores de asignación: se utilizan para asignar valores a variables. El operador de asignación básico es el signo igual (=). Además, existen operadores de asignación compuestos que combinan una operación aritmética y una asignación.

    1
    let x = 5; // Asignación básica
    2
    x += 3; // x = x + 3 (8)
    3
    x -= 2; // x = x - 2 (6)
    4
    x *= 4; // x = x * 4 (24)
    5
    x /= 3; // x = x / 3 (8)
    6
    x %= 5; // x = x % 5 (3)
  • Operadores de comparación: se utilizan para comparar valores y devuelven un valor booleano según la comparación sea verdadera o falsa. Estos pueden ser de igualdad (==), desigualdad (!=), mayor que (>), menor que (<), mayor o igual que (>=) y menor o igual que (<=).

    1
    let a = 5;
    2
    let b = 8;
    3
    4
    let igual = a == b; // false
    5
    let noIgual = a != b; // true
    6
    let mayor = a > b; // false
    7
    let menorIgual = a <= b; // true

    Debemos tener en cuenta un detalle de suma importancia, en JavaScript, la comparación de igualdad puede realizarse con con operadores distintos y los algoritmos de comparación para cada uno de ellos pueden variar dependiendo del tipo de dato. Fundamentalmente, debemos tener en cuenta que == realiza una comparación débil y === realiza una comparación estricta.

    Para más detalles sobre este tema, podemos consultar el anexo Comparación de igualdad en JavaScript.

  • Operadores lógicos: se utilizan para combinar o invertir expresiones booleanas.

    • Conjunción o AND: se representa con && y devuelve true si ambas expresiones son verdaderas.
    • Disyunción o OR: se representa con || y devuelve true si al menos una de las expresiones es verdadera.
    • Negación o NOT: se representa con ! y devuelve true si la expresión es falsa.
    1
    let x = 5;
    2
    let y = 10;
    3
    let z = 3;
    4
    5
    let resultado1 = (x < y) && (z > x); // true
    6
    let resultado2 = (x > y) || (z < y); // false
    7
    let resultado3 = !(x === y); // true

Estructuras de control

JavaScript proporciona varias estructuras de control que nos permiten controlar el flujo de ejecución de un programa y tomar decisiones basadas en ciertas condiciones, o repetir un grupo de instrucciones un número determinado de veces.

Antes de analizar las estructuras de control, es importante recordar que JavaScript establece bloques de código mediante llaves {}. Esto significa que, si queremos agrupar varias instrucciones debemos hacerlo mediante este mecanismo.

1
{
2
// Instrucción 1
3
// Instrucción 2
4
// Instrucción 3
5
}

Estructura if

La estructura if permite el control selectivo del flujo de ejecución de un programa. Se evalúa una condición y, si es verdadera, se ejecuta un bloque de código.

1
if (condicion) {
2
// Bloque de código a ejecutar si la condición es verdadera
3
}

Además, podemos agregar un bloque de código que se ejecutará si la condición no se cumple utilizando la estructura else.

1
if (condicion) {
2
// Bloque de código a ejecutar si la condición es verdadera
3
} else {
4
// Bloque de código a ejecutar si la condición es falsa
5
}

Asimismo, podemos encadenar múltiples condiciones utilizando la estructura else if. La estructura else if establece condiciones que se deben evaluar secuencialmente. Se comprueban las condiciones una tras otra hasta que se encuentra una condición verdadera y se ejecuta el bloque de código correspondiente, o hasta que se llega al bloque else si ninguna de las condiciones es verdadera.

1
if (condicion1) {
2
// Código a ejecutar si la condicion1 es verdadera
3
} else if (condicion2) {
4
// Código a ejecutar si la condicion2 es verdadera
5
} else if (condicion3) {
6
// Código a ejecutar si la condicion3 es verdadera
7
} else {
8
// Código a ejecutar si ninguna de las condiciones anteriores es verdadera
9
}

Estructura switch

La estructura switch se utiliza para realizar una selección múltiple en función del valor de una expresión. Se comparan diferentes casos y se ejecuta el código correspondiente al caso que coincida o, en su defecto, se puede especificar un caso por defecto.

Para establecer cada caso, se utiliza la palabra clave case, seguida del valor con el que se compara.

Por último, es importante recordar que, una vez que se ejecuta un caso, se debe utilizar la palabra clave break para salir de la estructura switch. De lo contrario, se continuarán evaluando los casos siguientes.

1
switch (expresion) {
2
case valor1:
3
// Código a ejecutar si la expresion coincide con valor1
4
break;
5
case valor2:
6
// Código a ejecutar si la expresion coincide con valor2
7
break;
8
default:
9
// Código a ejecutar si la expresion no coincide con ninguno de los casos anteriores
10
break;
11
}

Estructura for

La estructura for se utiliza para repetir un bloque de código un número específico de veces. Se compone de tres partes:

  • Inicialización: se ejecuta una vez antes de que comience la iteración. Se utiliza para inicializar la variable de control del bucle.
  • Condición: se evalúa antes de cada iteración. Si la condición es verdadera, se ejecuta el bloque de código. Si es falsa, se sale del bucle.
  • Incremento: se ejecuta después de cada iteración. Se utiliza para modificar la variable de control del bucle.
1
for (inicializacion; condicion; incremento) {
2
// Bloque de código a ejecutar en cada iteración
3
}

Estructura while

La estructura while se utiliza para repetir un bloque de código mientras se cumpla una determinada condición. La condición se evalúa antes de cada iteración.

1
while (condicion) {
2
// Bloque de código a ejecutar mientras la condición sea verdadera
3
}

Funciones

Las funciones son una parte fundamental de cualquier lenguaje de programación, ya que nos permiten encapsular un conjunto de instrucciones y reutilizarlas en diferentes partes de nuestro programa. Las funciones en JavaScript tienen la siguiente sintaxis básica:

1
function <nombre de función>(<lista de parámetros>) {
2
<bloque de código>
3
return <valor>;
4
}

Analizando la estructura de una función, podemos identificar los siguientes elementos:

  • function: es la palabra clave utilizada para declarar una función en JavaScript.
  • <nombre de función>: el identificador que le damos a una función al momento de definirla. Se utiliza para invocarla posteriormente.
  • <lista de parámetros>: una función puede recibir cero o más parámetros, los cuales son variables que se utilizan dentro de la función para realizar operaciones. Estos siempre se encuentran entre paréntesis y separados por comas.
  • <bloque de código>: es el conjunto de instrucciones que se ejecutan al invocar la función. Puede contener cualquier tipo de instrucción válida en JavaScript.
  • return: la sentencia return se utiliza para devolver un valor desde la función. Es opcional y se puede utilizar para devolver un resultado o finalizar la ejecución de la función.

Veamos un sencillo ejemplo para definición e invocación de una función en JavaScript:

1
function sumar(a, b) {
2
let resultado = a + b;
3
return resultado;
4
}
5
6
// Invocamos y almacenamos el resultado de la función en una variable
7
let suma = sumar(3, 5);
8
console.log(suma); // Salida: 8

Además de las funciones declaradas mediante la palabra clave function, JavaScript también admite funciones anónimas (funciones sin nombre) y funciones flecha (arrow functions), que proporcionan una sintaxis más compacta y funcionalidades adicionales.

Las funciones son una parte esencial de JavaScript, ya que permiten organizar y reutilizar el código, mejorar la modularidad y facilitar el mantenimiento de las aplicaciones.

Las funciones anónimas y las funciones flecha son dos formas alternativas de declarar funciones en JavaScript.

Funciones anónimas

Las funciones anónimas son aquellas que no tienen un nombre asignado. Se definen directamente como “expresiones de función” y se utilizan principalmente cuando se requiere una función en un contexto específico, como pasarla como argumento a otra función o asignarla a una variable.

1
let saludar = function(nombre) {
2
console.log("Hola, " + nombre + "!");
3
};

Al asignar una función anónima a una variable, podemos invocarla utilizando el nombre de la variable, como si fuera una función normal.

1
saludar("Juan"); // Salida: Hola, Juan!

En este caso, se declara una función anónima y se asigna a la variable saludar. Luego, se invoca la función pasando el nombre “Juan” como argumento.

Funciones flecha

Las funciones flecha son una forma abreviada y concisa de definir funciones en JavaScript.

Se denotan con el operador de flecha => y no requieren la palabra clave function. Son ideales para funciones anónimas y para situaciones donde se necesita una sintaxis más corta. Por ejemplo:

1
let saludar = (nombre) => {
2
console.log("Hola, " + nombre + "!");
3
};

Si una función flecha tiene un solo parámetro, los paréntesis pueden ser omitidos. Sin embargo, si no hay parámetros o hay más de uno, los paréntesis son obligatorios.

1
let saludar = nombre => {
2
console.log("Hola, " + nombre + "!");
3
};

Aún así, es una buena práctica mantener los paréntesis para evitar confusiones y mejorar la legibilidad del código.

Por último, podemos destacar que si la función flecha contiene solo una expresión, el valor de esa expresión se devuelve implícitamente sin necesidad de utilizar la palabra clave return. Si se necesita más de una expresión o un bloque de código, se deben utilizar las llaves {} y se debe especificar explícitamente la instrucción return si se desea devolver un valor.

1
let duplicar = (num) => num * 2; // Función flecha de una sola línea
2
3
let calcularPromedio = (num1, num2) => {
4
let suma = num1 + num2;
5
let promedio = suma / 2; // Funcion flecha con un bloque de codigo
6
return promedio;
7
};

Objetos

Debemos hacer una aclaración de este tipo de dato, ya que en el futuro estudiaremos el concepto de clases.

Los objetos son estructuras de datos que nos permiten almacenar propiedades y métodos relacionados. Pueden representar entidades del mundo real, como un usuario, un producto o cualquier otra cosa que necesitemos modelar en nuestro programa.

Los objetos pueden definirse de forma literal utilizando llaves ({}), dentro de las cuales se especifican las propiedades y los métodos del objeto.

  • Propiedades: son asociaciones entre un nombre (también conocido como clave) y un valor. En el paradigma orientado a objetos estos se denominan atributos e indican una característica de la entidad representada. El valor puede ser cualquier tipo de datos válido en JavaScript, como un número, una cadena de texto, un booleano, un arreglo u otro objeto.

  • Métodos: son funciones asociadas con el objeto (contenidas en el ámbito del objeto) y nos permiten realizar operaciones o cálculos relacionados con el objeto. Definen el comportamiento de la entidad representada.

1
const persona{
2
nombre: "Juan",
3
apellido: "Perez",
4
edad: 24,
5
saludo: function saludar(){
6
// Cuerpo de la función
7
}
8
}

Si lo comparamos con otros lenguajes de programación, como Java o Python, veremos que para instanciar un objeto es necesaria una clase que defina su estructura y comportamiento.

Cualquier objeto definido de forma literal será una instancia de la clase Object, la cual es la clase base de todos los objetos en JavaScript. Podemos notar esto si utilizamos el operador typeof para conocer el tipo de dato de un objeto.

1
let numero = 10;
2
console.log(typeof numero); // "number"
3
4
let texto = "Hola";
5
console.log(typeof texto); // "string"
6
7
let esVerdadero = true;
8
console.log(typeof esVerdadero); // "boolean"
9
10
let persona = { nombre: "Juan", edad: 25 };
11
console.log(typeof persona); // "object"

En el futuro, veremos que el tipo de dato de un objeto instanciado a partir de una clase definida por el usuario es también object. Por ejemplo, una clase predefinida en JavaScript es Date, la cual nos permite trabajar con fechas y horas.

1
let fecha = new Date();
2
console.log(typeof fecha); // "object"

Cabe aclarar que otra manera de crear objetos en JavaScript es utilizando directamente un constructor como Object(). Esta función crea un nuevo objeto y nos permite asignar propiedades y métodos al objeto de forma dinámica.

1
let persona = new Object();

No obstane, la forma más común y recomendada de crear objetos en JavaScript es utilizando la notación de objetos literales o bien, a partir de clases definidas por el usuario.

Más adelante, estudiaremos en detalle el concepto de clases en JavaScript.

Metodos de Arrays

Para concluir con este resumen, es importante mencionar que JavaScript proporciona varios métodos integrados para manipular y transformar arreglos (arrays).

  • push: Agrega uno o más elementos al final de un arreglo y devuelve la nueva longitud del arreglo.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    numeros.push(6);
    3
    console.log(numeros); // [1, 2, 3, 4, 5, 6]
  • pop: Elimina el último elemento de un arreglo y lo devuelve.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let ultimo = numeros.pop();
    3
    console.log(ultimo); // 5
    4
    console.log(numeros); // [1, 2, 3, 4]
  • unshift: Agrega uno o más elementos al inicio de un arreglo y devuelve la nueva longitud del arreglo.

    1
    let numeros = [2, 3, 4, 5];
    2
    numeros.unshift(1);
    3
    console.log(numeros); // [1, 2, 3, 4, 5]
  • shift: Elimina el primer elemento de un arreglo y lo devuelve.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let primero = numeros.shift();
    3
    console.log(primero); // 1
    4
    console.log(numeros); // [2, 3, 4, 5]
  • concat: Combina dos o más arreglos y devuelve un nuevo arreglo resultante.

    1
    let numeros1 = [1, 2, 3];
    2
    let numeros2 = [4, 5, 6];
    3
    let numerosCombinados = numeros1.concat(numeros2);
    4
    console.log(numerosCombinados); // [1, 2, 3, 4, 5, 6]
  • slice: Devuelve una copia superficial (shallow copy) de una porción de un arreglo en un nuevo arreglo.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let subarreglo = numeros.slice(1, 4);
    3
    console.log(subarreglo); // [2, 3, 4]
  • splice: Cambia el contenido de un arreglo eliminando, reemplazando o agregando elementos.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    numeros.splice(2, 1); // Elimina un elemento en la posición 2
    3
    console.log(numeros); // [1, 2, 4, 5]
    4
    5
    numeros.splice(2, 0, 3); // Agrega el número 3 en la posición 2
    6
    console.log(numeros); // [1, 2, 3, 4, 5]
    7
    8
    numeros.splice(2, 1, 6); // Reemplaza el número 3 por el número 6 en la posición 2
    9
    console.log(numeros); // [1, 2, 6, 4, 5]
  • forEach: Ejecuta una función dada una vez por cada elemento del arreglo.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    numeros.forEach(function(numero) {
    3
    console.log(numero);
    4
    });
  • map: Crea un nuevo arreglo con los resultados de aplicar una función a cada elemento del arreglo.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let cuadrados = numeros.map(function(numero) {
    3
    return numero * numero;
    4
    });
    5
    console.log(cuadrados); // [1, 4, 9, 16, 25]
  • filter: Crea un nuevo arreglo con todos los elementos que pasen una prueba (función de filtrado) específica.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let pares = numeros.filter(function(numero) {
    3
    return numero % 2 === 0;
    4
    });
    5
    console.log(pares); // [2, 4]
  • find: Devuelve el primer elemento en el arreglo que cumple con una condición dada.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let mayorQueTres = numeros.find(function(numero) {
    3
    return numero > 3;
    4
    });
    5
    console.log(mayorQueTres); // 4
  • findIndex: Devuelve el índice del primer elemento en el arreglo que cumple con una condición dada.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let indiceMayorQueTres = numeros.findIndex(function(numero) {
    3
    return numero > 3;
    4
    });
    5
    console.log(indiceMayorQueTres); // 3
  • reduce: Aplica una función a un acumulador y a cada elemento del arreglo (de izquierda a derecha) para reducirlo a un solo valor.

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    let suma = numeros.reduce(function(acumulador, numero) {
    3
    return acumulador + numero;
    4
    }, 0);
    5
    console.log(suma); // 15
  • sort: Ordena los elementos de un arreglo in situ (modifica el arreglo original) o devuelve un nuevo arreglo ordenado.

    1
    let numeros = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
    2
    numeros.sort();
    3
    console.log(numeros); // [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
  • reverse: Invierte el orden de los elementos de un arreglo in situ (modifica el arreglo original).

    1
    let numeros = [1, 2, 3, 4, 5];
    2
    numeros.reverse();
    3
    console.log(numeros); // [5, 4, 3, 2, 1]

El término “in situ” se refiere a realizar una operación o modificación directamente en el lugar o en el contexto original, sin crear una copia o un nuevo objeto. En el contexto de los métodos de manipulación de arreglos en JavaScript, “in situ” significa que la operación se realiza directamente en el arreglo original, modificando su contenido sin crear un nuevo arreglo.

Bibliografía