Manual Completo de JavaScript Vanilla

Introducción a JavaScript

JavaScript es un lenguaje de programación interpretado, orientado a objetos, utilizado principalmente en el desarrollo web para añadir interactividad a las páginas.

JavaScript vs ECMAScript: ECMAScript es la especificación del lenguaje, mientras que JavaScript es la implementación más popular de esta especificación.

¿Dónde colocar JavaScript?

Puedes incluir JavaScript en tu HTML de tres formas:

<!-- 1. En línea (no recomendado para código extenso) -->
<button onclick="alert('Hola')">Click me</button>

<!-- 2. En el head o body con etiquetas script -->
<script>
    console.log('Hola desde el script interno');
</script>

<!-- 3. Archivo externo (mejor práctica) -->
<script src="app.js" defer></script>
Mejores prácticas: Para evitar problemas de renderizado, coloca los scripts al final del body o usa los atributos defer o async.

Fundamentos de JavaScript

Variables y constantes

// Formas antiguas (evitar)
var nombre = "Juan";

// Formas modernas (ES6+)
let edad = 30;          // Variable mutable
const PI = 3.1416;      // Constante (no puede reasignarse)
Scope: var tiene scope de función, mientras que let y const tienen scope de bloque.

Tipos de datos

// Primitivos
let cadena = "Hola Mundo";      // String
let numero = 42;                // Number
let booleano = true;            // Boolean
let nulo = null;                // Null
let indefinido = undefined;     // Undefined
let simbolo = Symbol('id');     // Symbol (ES6)
let bigInt = 9007199254740991n; // BigInt (ES2020)

// Objetos
let objeto = { nombre: "Juan", edad: 30 };
let array = [1, 2, 3];
let fecha = new Date();

Operadores

// Aritméticos
let suma = 5 + 3;       // 8
let modulo = 10 % 3;    // 1 (resto de la división)

// Comparación
5 == '5';   // true (solo valor)
5 === '5';  // false (valor y tipo)

// Lógicos
true && false;  // AND → false
true || false;  // OR → true
!true;          // NOT → false

// Ternario
let resultado = (edad >= 18) ? 'Mayor' : 'Menor';

Estructuras de control

Condicionales

// if-else
if (edad >= 18) {
    console.log("Mayor de edad");
} else if (edad >= 13) {
    console.log("Adolescente");
} else {
    console.log("Niño");
}

// switch
switch(diaSemana) {
    case 1:
        console.log("Lunes");
        break;
    case 2:
        console.log("Martes");
        break;
    default:
        console.log("Otro día");
}

Bucles

// for clásico
for (let i = 0; i < 5; i++) {
    console.log(i);
}

// while
let j = 0;
while (j < 5) {
    console.log(j);
    j++;
}

// do-while
let k = 0;
do {
    console.log(k);
    k++;
} while (k < 5);

// for...of (para arrays)
const frutas = ['manzana', 'pera', 'uva'];
for (const fruta of frutas) {
    console.log(fruta);
}

// for...in (para propiedades de objetos)
const persona = { nombre: 'Juan', edad: 30 };
for (const propiedad in persona) {
    console.log(`${propiedad}: ${persona[propiedad]}`);
}

Funciones

Declaración de funciones

// Función declarada
function saludar(nombre) {
    return `Hola ${nombre}`;
}

// Función expresada
const sumar = function(a, b) {
    return a + b;
};

// Arrow function (ES6+)
const multiplicar = (a, b) => a * b;

// Parámetros por defecto
function crearUsuario(nombre, rol = 'usuario') {
    return { nombre, rol };
}

Scope y closures

function contador() {
    let count = 0;
    
    return function() {
        count++;
        return count;
    };
}

const incrementar = contador();
console.log(incrementar()); // 1
console.log(incrementar()); // 2
Closure: Una función que recuerda su entorno léxico (variables en scope cuando fue creada), incluso cuando se ejecuta fuera de ese entorno.

Objetos y Prototipos

Creación de objetos

// Literal
const persona = {
    nombre: 'Juan',
    edad: 30,
    saludar: function() {
        console.log(`Hola, soy ${this.nombre}`);
    }
};

// Constructor
function Persona(nombre, edad) {
    this.nombre = nombre;
    this.edad = edad;
    this.saludar = function() {
        console.log(`Hola, soy ${this.nombre}`);
    };
}
const juan = new Persona('Juan', 30);

// Class (ES6)
class Persona {
    constructor(nombre, edad) {
        this.nombre = nombre;
        this.edad = edad;
    }
    
    saludar() {
        console.log(`Hola, soy ${this.nombre}`);
    }
}
const maria = new Persona('María', 25);

Prototipos

// Añadir método al prototipo
Persona.prototype.despedirse = function() {
    console.log(`Adiós, soy ${this.nombre}`);
};

// Herencia de prototipos
class Estudiante extends Persona {
    constructor(nombre, edad, curso) {
        super(nombre, edad);
        this.curso = curso;
    }
    
    estudiar() {
        console.log(`${this.nombre} está estudiando ${this.curso}`);
    }
}

Arrays y métodos

Manipulación básica

const numeros = [1, 2, 3, 4, 5];

// Añadir/eliminar elementos
numeros.push(6);        // Añade al final
numeros.pop();          // Elimina del final
numeros.unshift(0);     // Añade al inicio
numeros.shift();        // Elimina del inicio

// Acceso
numeros[0];             // Primer elemento
numeros[numeros.length - 1]; // Último elemento

Métodos importantes

// map - transformar elementos
const dobles = numeros.map(n => n * 2);

// filter - filtrar elementos
const pares = numeros.filter(n => n % 2 === 0);

// reduce - reducir a un valor
const suma = numeros.reduce((acc, n) => acc + n, 0);

// find - encontrar elemento
const mayor3 = numeros.find(n => n > 3);

// some/every - comprobar condición
const hayPares = numeros.some(n => n % 2 === 0);
const todosPares = numeros.every(n => n % 2 === 0);

// sort - ordenar (cuidado con números)
const ordenados = numeros.sort((a, b) => a - b);

Asincronía en JavaScript

Callbacks

function obtenerDatos(callback) {
    setTimeout(() => {
        callback(null, { datos: 'Información importante' });
    }, 1000);
}

obtenerDatos((error, datos) => {
    if (error) {
        console.error(error);
        return;
    }
    console.log(datos);
});

Promesas

function obtenerDatos() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ datos: 'Información importante' });
            // o reject(new Error('Algo salió mal'));
        }, 1000);
    });
}

obtenerDatos()
    .then(datos => console.log(datos))
    .catch(error => console.error(error));

Async/Await

async function procesarDatos() {
    try {
        const datos = await obtenerDatos();
        console.log(datos);
    } catch (error) {
        console.error(error);
    }
}

procesarDatos();

Manipulación del DOM

Selección de elementos

// Métodos clásicos
document.getElementById('miId');
document.getElementsByClassName('miClase');
document.getElementsByTagName('div');

// Métodos modernos (querySelector)
document.querySelector('#miId');             // Primer elemento que coincida
document.querySelectorAll('.miClase');       // Todos los elementos

Manipulación básica

const elemento = document.querySelector('#miElemento');

// Contenido
elemento.textContent = 'Nuevo texto';       // Solo texto
elemento.innerHTML = '<strong>Texto</strong>'; // HTML

// Atributos
elemento.setAttribute('data-id', '123');
elemento.getAttribute('data-id');
elemento.removeAttribute('data-id');

// Clases
elemento.classList.add('nueva-clase');
elemento.classList.remove('vieja-clase');
elemento.classList.toggle('activo');

// Estilos
elemento.style.color = 'red';
elemento.style.backgroundColor = '#f0f0f0';

Eventos

// Añadir evento
elemento.addEventListener('click', function(e) {
    console.log('Elemento clickeado', e.target);
});

// Eventos comunes
// click, dblclick, mouseenter, mouseleave
// keydown, keyup, keypress
// submit, change, input
// load, DOMContentLoaded, resize, scroll

Características modernas (ES6+)

Destructuring

// Arrays
const [primero, segundo] = [1, 2, 3];

// Objetos
const { nombre, edad } = { nombre: 'Juan', edad: 30 };

// Parámetros de función
function mostrarDatos({ nombre, edad = 20 }) {
    console.log(nombre, edad);
}

Spread y Rest

// Spread (expandir)
const numeros = [1, 2, 3];
const nuevosNumeros = [...numeros, 4, 5];

const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };

// Rest (agrupar)
function sumar(...nums) {
    return nums.reduce((acc, n) => acc + n, 0);
}

Módulos

// Exportar (en archivo math.js)
export const PI = 3.1416;
export function sumar(a, b) { return a + b; }
export default function restar(a, b) { return a - b; }

// Importar (en otro archivo)
import restar, { PI, sumar } from './math.js';

Patrones y Buenas Prácticas

Patrones comunes

// Módulo (patrón de encapsulación)
const miModulo = (function() {
    let contador = 0;
    
    function incrementar() {
        contador++;
    }
    
    function obtenerContador() {
        return contador;
    }
    
    return {
        incrementar,
        obtenerContador
    };
})();

// Singleton
class Configuracion {
    constructor() {
        if (!Configuracion.instancia) {
            this.apiUrl = 'https://api.example.com';
            Configuracion.instancia = this;
        }
        return Configuracion.instancia;
    }
}

Buenas prácticas

Temas Avanzados

Generadores

function* generadorId() {
    let id = 1;
    while (true) {
        yield id;
        id++;
    }
}

const gen = generadorId();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

Proxy

const persona = { nombre: 'Juan', edad: 30 };
const proxy = new Proxy(persona, {
    get(target, prop) {
        if (prop in target) {
            return target[prop];
        }
        return `La propiedad "${prop}" no existe`;
    },
    set(target, prop, value) {
        if (prop === 'edad' && typeof value !== 'number') {
            throw new Error('La edad debe ser un número');
        }
        target[prop] = value;
        return true;
    }
});

Web Workers

// main.js
const worker = new Worker('worker.js');
worker.postMessage('Iniciar trabajo');
worker.onmessage = function(e) {
    console.log('Mensaje del worker:', e.data);
};

// worker.js
self.onmessage = function(e) {
    console.log('Mensaje del main:', e.data);
    // Procesamiento pesado aquí
    self.postMessage('Trabajo completado');
};

Conclusión

JavaScript es un lenguaje poderoso y versátil que ha evolucionado significativamente en los últimos años. Este manual cubre desde los conceptos más básicos hasta temas avanzados, pero JavaScript tiene mucho más que ofrecer.

Recursos adicionales: