Vamos a ver las nociones básicas sobre cómo empezar a programar en JavaScript con este tutorial a base de explicaciones sencillas y ejemplos útiles desde cero.
Para empezar, ten en cuenta que el código JavaScript se incluye en el documento HTML mediante la etiqueta <script>, que tiene cláusulas de apertura y cierre. Si tienes dudas sobre el funcionamiento de HTML empieza por aquí.
Índice de contenidos del artículo
En el siguiente ejemplo vemos que dentro la etiqueta script hay dos llamadas a funciones o métodos. Alert y document.write. El primero muestra un mensaje al usuario en una ventanita y el segundo sustituye el contenido del documento HTML por el texto introducido entre comillas.
Cada instrucción de código lleva al final un punto y coma.
Podemos ubicar los scripts donde queramos dentro del documento y también se puede enlazar a un archivo externo .js en el que se encuentre el código.
Aunque podemos ubicar el código JavaScript en cualquier parte del documento HTML, cuando dentro del código se haga referencia a un elemento del documento HTML, este código debe aparecer después del elemento o emplear algún método que espere a que se cargue todo el documento para ejecutar el script.
En general, pondremos la etiqueta script en la parte final del body de nuestro documento HTML.
Adicionalmente podemos ejecutar código JS directamente en la consola de las herramientas para desarrolladores del navegador. Las herramientas para desarrolladores de Firefox o navegadores basados en Chromium como Google Chrome son muy potentes y útiles.
Puedes aprender más sobre cómo comentar adecuadamente en mi artículo sobre manuales de usuario y documentación JavaScript con JSDoc.
Tu amiga la consola es una herramienta esencial cuando desarrollamos en JS. Con estos métodos a continuación podemos enviar diferentes tipos de mensaje a la consola del navegador:
El signo igual, =, es el operador de asignación. Con él damos valor a las variables y las variables sirven para almacenar datos bajo un nombre descriptivo que le damos.
Supongamos una variable de nombre nota, que servirá para almacenar la nota de un alumno.
nota = 5;
Con el operador asignación hemos especificado que el valor de la variable nota pase a ser 5.
A partir de ese momento, cuando utilicemos la palabra nota dentro del código, será equivalente a un 5.
Si más adelante en el código volvemos a asignar otro valor a la misma variable, perderemos el valor anterior y guardaremos el nuevo valor.
nota = 7;
Ahora hemos asignado un 7 a la variable nota.
Los operadores aritméticos son para realizar operaciones matemáticas. Tenemos la suma +, la resta -, la multiplicación * o la división /.
Para operar, simplemente utilizamos dos valores separados por el operador aritmético.
50 + 5; //Suma 50 y 5, el resultado sería 55.
También podemos operar con variables.
nota * 10; //Multuplica el valor que tenga la variable nota por 10.
Lo normal es almacenar el resultado de las operaciones en variables.
media = nota1 + nota2 / 2
En el ejemplo anterior guardamos el resultado de la operación para calcular la media en una variable llamada media.
Por otro lado, en estructuras condicionales if o bucles while, tenemos expresiones lógicas que comparan dos valores entre sí mediante un operador lógico.
if (nota < 5)
console.log("insuficiente");
En el ejemplo anterior estamos enviando a la consola el mensaje insuficiente en caso de que el valor de la variable nota sea menor que 5.
En este caso se ha empleado el operador lógico menor que, <.
Los operadores lógicos son:
Adicionalmente podemos unir u operar con varias condiciones lógicas con && //AND o Y lógico, || //OR u O lógico
if ((nota >= 5) && (nota<6)){
console.log("Suficiente");
};
El ejemplo anterior compararía la nota con 5 y con 6 para determinar si el resultado es suficiente.
Tenemos 3 formas de crear variables en JavaScript. Las variables son el pilar fundamental de cualquier lenguaje de programación; con ellas podemos almacenar datos y operar con ellos.
Mediante la palabra reservada var creamos o declaramos una variable en JavaScript.
var profe = 'Diego';
En el ejemplo anterior hemos declarado una variable llamada “profe” y le hemos dado como valor la palabra “Diego”.
Mediante el operador de igualdad estamos realizando una asignación. Es decir, que a partir de ese momento, la variable profe contiene la cadena de caracteres Diego.
Podemos crear también variables mediante las palabras reservadas let y const.
let numero=300;
const boo = true;
Si ahora envías a la consola esas variables, verás que se muestra se forma similar, únicamente hemos asignado un tipo de dato distinto a cada una de ellas. Pero esto no tiene que ver con que sea let o const. JS tiene la flexibilidad de al macenar distintos tipos de dato en sus variables sin especificarlo.
Una vez que las variables están creadas, podemos utilizarlas y volver a asignarles valor, esta vez sin tener que usar la palabra reservada para declararla. La variable ya existe, simplemente le estamos dando otro valor:
numero="Esto no es un número";
Fíjate que a la variable número, que antes almacenaba un valor numérico, ahora le hemos asignado una cadena de texto. Además, antes asignamos el valor ‘Diego’ a la variable profe con comillas simples y ahora a número con comillas dobles. Esta versatilidad es característica de JavaScript y todas las opciones son posibles.
De los 3 tipos de variable que hemos visto, const es para almacenar valores constantes y por tanto, no se pueden volver a asignar; var y let sí permiten que cambie su valor.
Las variables de tipo var, tienen un alcance de función y las variables let de bloque. Let y const aparecen en la versión ES6 y se puede decir que son más apropiadas, ya que permacen menos tiempo en memoria.
El scope o alcance, define dónde tenemos o no tenemos accesibles las variables.
Las variables globales son quelllas que creamos en cualquier parte del script que no sea un bloque de código, objeto o función.
Estas están siempre accesibles desde cualquier otra parte del documento, incluso otro script en el mismo HTML o dentro de un bloque o función.
Esto mismo ocurre también con las funciones. Que son First class citicens y serían accesibles desde cualquier otra parte del documento.
Las variables de función son aquellas que son creadas dentro de una función y por tanto sólo son accesibles mientras se ejecuta la función.
Esto se hace por seguridad, ya que si hemos dicho que podemos llamar a las funciones tantas veces como queramos, si las variables creadas dentro de las funciones actuaran como globales, sus valores se machacarían una y otra vez y perderíamos el control.
A esto lo llamaremos local scope o ámbito local.
Las variables de bloque son aquellas que no persisten fuera de un bloque de código, es decir, fuera de unas llaves {}.
Por definición, let y const son variables de bloque.
if (1 === 1) {
let bien = true;
}
console.log(bien)
La línea anterior de código dará un error, ya que la variable bien, declarada dentro del bloque, no es accesible desde fuera.
Para solucionarlo podríamos declarar la variable antes del bloque de código y luego asignarle el valor dentro.
let bien;
if (1 === 1) {
bien = true;
}
console.log(bien)
Aunque esta solución no sería del todo idónea con tal de evitar la creación de variables globales en la medida de lo posible.
Lo deberíamos encapsular todo en una función.
Las variables funcionan pongamos el nombre que pongamos, salvo que empleemos un nombre reservado para otra funcionalidad.
Sin embargo, hay convenciones que debemos utilizar para seguir buenas prácticas y que el código sea más legible.
Veamos estas reglas o convenciones:
let variableCamelCase;
Sirven para guardar texto y se pueden expresar con comillas simples, dobles o traseras.
const profe = "Diego";
const mates = 'cinco';
const pais = `Guatemala`;
Puede darse el caso de que necesitemos poner una comilla dentro del contenido. Para que se interprete adecuadamente y se de porfinalizada la cadena de texto antes de tiempo, empleamos la barra inclinada hacia atrás, “\”.
//esto de mostraría en pantalla como "Kevin's bike".
const fraseEnIngles = 'Kevin\'s bike';
//también podemos usar otro tipo de comillas
const frase2 = "Kevin's plane";
Una funcionalidad muy útil de usar la comilla trasera es que si ponemos saltos de línea dentro del string, estos se respetan cuando se muestre, lo cual viene genial cuando incluimos código HTML en nuestro JS.
const texto = `<code>Sííí!!,
DAME
MAS!!`;</code>
//se mostraría en pantalla tal como lo hemos expresado
const codigoHtml = <code>`<h1>Hola mundo</h1>
<p>Párrafo de ejemplo</p></code>`;
La concatenación consiste en unir elementos dentro de una cadena de texto. Para ello usaremos el operador + y normalmente lo usaremos para unir strings con variables. Por ejemplo,
let frase = "El resultado de la operación es: " + resultado;
//podemos concatenar tantas veces como queramos
let frase2 = "El número " + numero + "es par y múltiplo de " + numero2;
Otro tipo de notación con las comillas traseras sería la siguiente:
let frase = `El resultado es ${resultado}`;
En la que, como podemos observar, aparece la variable dentro de ${}.
También podemos hacer cálculos dentro:
let frase = `El resultado es ${1 * 100}`;
Ya hemos visto que podemos asignar números facilmente a nuestras variables.
Una funcionalidad muy útil es la palabra reservada typeof.
Con typeof podemos obtener el tipo de dato que tiene una variable en función de su valor.
Escribe el siguiente código en tu script:
let texto = "Diego";
let numero = 100;
Y luego prueba a poner en la consola lo siguiente:
typeof texto
typeof numero
Es especialmente útil cuando el usuario introduce un dato y queremos controlar su tipo.
Para trabajar con números disponemos de una serie de métodos de ayuda para los cálculos.
Prueba a poner en la consola Math. y verás todos los que hay. Prueba por ejemplo Math.round() o Math.random().
const lacasitos = 20;
const nenes = 3;
const lacasitosPorNene = Math.floor(lacasitos / nenes);
const aPapiLeQuedan = lacasitos % nenes;
console.log(`Cada nene obtiene ${lacasitosPorNene} y a Papi le quedan ${aPapiLeQuedan}`);
Los datos buleanos son binarios, es decir, que sólo aceptan los valores 0 y 1. Se pueden usar para cualquier cosa que sólo pueda tener 2 valores, como para expresar encendido o apagado, verdadero o falso, etc.
A las variables booleanas sólo podemos asignarle 0 o 1 y true o false, aunque con ellas quieras expresar otro comportamiento, como lo de encendido y apagado.
let respuesta = true;
Podemos realizar operaciones lógicas con tipos de datos buleanos. Por ejemplo:
const edad = 18;
const esMenor = edad < 19;
Veamos más operadores lógicos.
Ya hemos visto el operador asignación =, con el que damos un valor a una variable.
Operadores lógicos son ==, para conocer si dos datos son iguales, menor que <, mayor que >, menor o igual que <=, mayor o igual que >= y distinto.
Adicionalmente contamos con el operador ===, triple igual, con el que aplicamos restricciones de tipo también a la condición de igualdad. Es decir, que si los datos son iguales pero no comparten tipo de dato, en la doble igualdad daría verdadero y con la triple igualdad falso.
Prueba a ejecutar las siguientes líneas en la consola:
10 == 10
10 === 10
10 == "10"
10 === "10"
Null y undefined son dos formas de expresar “nada” en JavaScript.
Si creamos una variable y no le asignamos nada, esta tendrá el valor undefined por defecto.
let cosa;
console.log(cosa);
Null es el valor “nada” y lo podemos asignar:
let cosa = null;
Sirven para crear propiedades o identificadores únicas y por el momento no nos debemos preocupar por ellos, ya que se usan de forma más avanzada.
Los objetos los podemos definir como colecciones de datos personalizados y asociados entre sí de algún modo.
Los objetos pueden contener atributos y métodos. Para definirlos usamos las llaves {} y los asignamos con dos puntos :
const persona = {
nombre: 'Diego',
apellido: 'Martín',
edad: 30
};
Prueba ahora a inspeccionar ese objeto en la consola y a hacerle un typeof. Observa que puede que el orden de los atributos no sea el mismo.
También podemos definir los atributos de un objeto con puntos:
persona.nombre = 'Diego';
persona.apellido = 'Martín';
persona.edad = 30;
Lo primero que debemos saber de las funciones es que las podemos definir o crear para determianr su funcionamiento y también podemos invocarlas o llamarlas para hacer uso de ellas.
Vamos primero a centrarnos en cómo usar funciones que ya están creadas en JavaScript y por tanto, podemos hacer uso de ellas.
La llamada a una función tiene la siguiente sintaxis:
nombreFuncion();
Como podemos observar, es casi igual que una variable, con la diferencia de que tiene paréntesis al final. En estos paréntesis podemos introducir “argumentos” si la función lo permite. Estos argumentos son datos de entrada con los que la función operará para conseguir el objetivo para el que se ha diseñado.
nombreFuncion(arg1, arg2);
Por otro lado, las funciones puden devolver el resultado del cálculo que hagan, por lo que, si una función devuelve algún tipo de información de salida, podríamos asignarla a una variable para almacenar su resultado.
let resultado = nombreFuncion(arg1, arg2);
Previamente hemos dicho que los objetos tienen atributos (variables) o métodos. Los métodos serían funciones que forman parte de objetos. De este modo, siguiendo la misma sintáxis que hemos visto previamente, un ejemplo de llamada a un método sería:
objeto.metodo();
Hemos usado ya en varias ocasiones el método log del objeto console con console.log(). Hemos comprobado que le introducimos cadenas de texto como argumento y este método envía esa información a la consola.
Además, si te has fijado, justo debajo aparece el mensaje Undefined. Esto es porque no se ha definido un valor de salida para este método.
Prueba por ejemplo a calcular el máximo de dos números jugando con el método Math.max() en la consola para ver su salida.
Math.max(10,12);
Veamos ahora algunas funciones y métodos ya definidos en JavaScript que son de gran utilidad.
Podemos enviar contenido al HTML mediante el método write de la clase document:
document.write("Cadena de texto o una variable como n concatenando con +: " + n);
Es importante tener en cuenta que si empleamos document.write cuando la página está completamente cargada, todo el contenido se sustituye. En realidad se emplea normalmente en entornos de prueba o para cuando abrimos nuevas ventanas con contenido en función de un evento del usuario.
Recomendable leer y ver los ejemplos de W3Schools. Veremos ejemplos de uso más adelante.
La función promt() nos permite abrir un cuadro de diálogo al usuario para que introduzca un dato. Podemos pasarle como parámetro una cadena de caracteres que se mostrará y nos devuelve una cadena de texto.
prompt("Introduzca número");
Lo que ocurre es que, como hemos dicho, esta función devuelve una cadena de texto. Si queremos trabajar exclusivamente con números debemos convertir esa cadena de texto a número mediante la función parseInt(), a la que se le introduce una cadena de texto como parámetro y devuelve el valor en formato numérico.
numero=parseInt("5");
Si unimos ambas funciones en la misma sentencia tenemos el dato introducido por el usuario en formato numérico:
numero=parseInt(prompt("Introduzca número"));
También se puede usar la función Number para convertir texto a números:
// parsing:
parseInt("20px"); // 20
parseInt("10100", 2); // 20
parseInt("2e1"); // 2
// type conversion
Number("20px"); // NaN
Number("2e1"); // 20, exponential notation
Con la función confirm podemos hacer una pregunta al usuario en un cuadro de diálogo en el que el este puede afirmar o no y en tal caso la función devolverá verdadero o falso respectivamente.
var v = confirm("¿Quieres enviarlo?");
if ( v ) {
document.write("Ok, gracias.");
} else {
document.write("Estaremos aquí para cuando te decidas ;)");
}
Para definir una función en JS usamos la palabra reservada function y después le ponemos un nombre seguido de los paréntesis. A continuación de los paréntesis un bloque de código en el que escribimos las sentencias que especifican su comportamiento.
Dentro de los paréntesis pueden ir argumentos y adicionalmente podemos especificar el valor que devuelve mediante la palabra reservada return.
function calcularAlgo(){
console.log("Calculando...");
}
Veamos un ejemplo un poco más avanzado. Supongamos que queremos aplicar un 20% de descuento en un producto que vale 100.
function aplicarDescuento(){
const descuento = 100 * 0.2;
}
En el ejemplo anterior se observa que no podemos acceder a la variable que hemos declarado en el interior de la función desde fuera de ella. Esto es lo que antes mencionábamos del ámbito o scope.
Para poder obtener el resultado de la función usaremos la palabra reservada return.
function aplicarDescuento(){
const descuento = 100 * 0.2;
return descuento;
}
Veamos que podemos simplemente obtener el descuento llamando a la función o bien podemos asignar la llamada a otra variable para que esta almacene el dato.
Es común preguntarse ahora qué sentido tiene crear fuera de la función una variable que almacene el mismo dato que ya tenía una variable dentro de la función. Para explicarlo volvemos al scope.
Decíamos que las variables let y const tienen ámbito de bloque. Eso quiere decir que su vida útil se extiende únicamente dentro del bloque donde son creadas y una vez que la ejecución del mismo finaliza, la variable es liberada de memoria por el recolector de basura, garbage collector en inglés. Puedes aprender más aquí sobre Cómo funciona JavaScript con ejemplos.
La función que hemos descrito en el apartado anterior es en realidad poco útil, ya que hace un cálculo muy específico. Lo ideal sería que se aplicara un descuento personalizado sobre un precio personalizado.
Esto lo logramos gracias a los argumentos de las funciones en JavaScript.
Si a la función anterior le espcificamos que como entrada deben introducirnos el descuento y el precio del producto…
function aplicarDescuento(precioProducto, desc){
const descuentoAplicado = precioProducto * (desc / 100);
return descuentoAplicado;
}
En el ejemplo anterior hemos modificado el código de la función para agregarle el precio del proudcto y el descuento como argumentos y dentro del bloque de código estamos operando con esos mismos datos.
Para hacer uso de esa función solicitando además al usuario que introduzca el dato, podemos hacer uso prompt(), tal como hemos visto previamente.
descuento = parseInt(prompt("Introduzca descuento"));
aplicarDescuento(50, descuento);
También podemos acortarlo aún más en una sóla línea:
aplicarDescuento(50, parseInt(prompt("Introduzca descuento")));
En el ejemplo anterior estamos indicando un precio del producto de 50 y el descuento lo pedimos al usuario por teclado.
Ahora vamos a suponer que queremos trabajar con los datos en variables que pudieran estar establecidas previamente en el código.
const precioZapatos = 100;
let descuentoZapatos = 20;
aplicarDescuento(precioZapatos, descuentoZapatos);
Digamos que cuando establecemos parámetros en una función, les ponemos un nombre descriptivo de variables que no existen hasta que les damos un valor en la llamada a la función.
Dentro de la función, operamos con estos valores que se dan cada vez que la función es llamada, con diferentes valores como parámetro.
En este momento, JavaScript crea variables temporales con el mismo nombre que los argumentos y que están disponibles mientras dura la ejecución de la función.
Debido a los anterior, podríamos llamar a nuestra función tantas veces como queramos con distintos valores en sus parámetros de entrada o podríamos crear diversas funciones que tengan los mismos argumentos.
function aplicarDescuento(precioProducto, desc){...};
function aplicarDescuentoFinal(precioProducto, desc){...};
descontado = aplicarDescuento(100,15);
descontado2 = aplicarDescuento(120,30);
Para concer mejor cómo funciona esto, mira los vídeos de mi artículo Cómo funciona JavaScript con ejemplos.
Adicionalmente, podemos establecer valores por defecto en los parámetros de las funciones, de forma que si la función es llamada sin argumentos, esta trabajaría con el valor por defecto.
Para asignar un valor por defecto, simplemente lo asginamos en la declaración de la función.
function diHola(nombre = 'tú'){
return "Hola " + nombre + ".";
}
La función anterior devolverá el mensaje “Hola tú.” si al llamar a la función no se espcifica ningún parámetro y concatenerá el valor indicado en caso de introducir una cadena de texto como argumento.
diHola();
diHola('Diego');
Ejercicio propuesto:
Realiza una función que calcule el importe total de una factura agregando el IVA y descontanto el IRPF.
IVA tiene un valor predefnido del 21% e IRPF del 15%.
Hasta ahora hemos visto la forma normal de crear o declarar funciones. También podemos crearlas como una expresión:
let saludar = function(nombre){
return "Hola " + nombre;
}
El uso o llamada de esta función como expresión sería igual al habitual
saludar('Diego');
¿Qué diferencia tiene entonces la declaración de una función como expresión respecto a la forma normal, especificando el nombre de la función?
console.log(saludar);
console.log(saludar2);
function saludar2(nombre){
return "Hola " + nombre;
}
let saludar = function(nombre){
return "Hola " + nombre;
}
En el código anterior veremos que llamada a la función como expresión no funcionará, mientras que la llamada a la función con nombre sí.
La primera nos mostrará un error que indica que la función no existe.
El hoisting lo que hace es facilitar el acceso a la declaración normal de la función, independientemente de dónde esté esta declarada.
En realidad es como si la declaración de la función saluda2 hubiera sido declarada antes de la llamada a la misma.
En el error anterior también vemos que ha denominado a algo anónimo. Esto sería eun ejemplo de una declaración de una función anónima:
function (nombre){
return "Hola " + nombre;
}
Como podemos observar, la parte derecha de nuestra expresión en el ejemplo de la función saluda(), era una función anónima y estaba siendo asignada a una variable.
El hoisting también aplica a la decalración de variables. Es decir, que si declaramos una variable tras haberla usado, esto funcionará. Aunque, ¡ojo! Estamos hablando de su declaración, no asignación.
console.log(edad);
let edad = 30;
El código anterior no dará error al tratar de mostrar la edad, porque la variable existe debido al hoisting, pero su asignación aún no se ha ejecutado, por ello mostrará undefined. Por lo mismo, el hoisting no tendrá efecto en funciones como expresión o arrow functions.
La sintáxis de funciones en forma de flecha se ha creado simplemente para ahorrar líneas de código y ahorrar tiempo.
Vemos paso a paso cómo trasnformar una declaración de función clásica o normal a una Arrow Function.
//tenemos una función normal
function pulgadaACm(pulgadas){
return pulgadas * 2.54;
};
//la transformamos a anónima como expresión
const pulgadaACm = function(pulgadas){
return pulgadas * 2.54;
};
//le quitamos la palabra reservada function y le ponemos una flecha
const pulgadaACm = (pulgadas) => {
return pulgadas * 2.54;
};
//ahora transformamos el return en un implícito
const pulgadaACm = (pulgadas) => pulgadas * 2.54;
//Si sólo hay un parámetro podemos ahorrarnos el peréntesis también
const pulgadaACm = pulgadas => pulgadas * 2.54;
Trata ahora de hacerlo tú con la siguiente:
function suma(a, b =3){
return a+b;
};
Antes hemos dicho que la parte derecha de función creada como expresión era una función anónima.
Las funciones anónimas por sí mismas sólo tienenn sentido si se ejecutan justo en el momneto de la declaración.
Para ello debemos ponerlas dentro de paréntesis y agregarles unos paréntesis detrás, como cuando especificamos una función sin parámetros:
(function(){
console.log("Ejecutando función anónima");
return "Genial!!";
})();
Así sería un ejemplo con un parámetro:
(function(edad){
console.log("Ejecutando función anónima");
return "Genial!!. Tu edad " + edad;
})(30);
Ya hemos visto los métodos y hemos puesto ejemplos. Repasemos
Hemos llamado ya en muchas ocasiones a console.log().
log() sería la función o método que pertenece al objeto console.
Por tanto, los métodos son funciones que forman parte de un objeto.
Prueba a poner “console” en la consola para ver todos los métodos disponibles en el objeto.
Vamos ahora a crear nuestro propio objeto con métodos.
const persona = {
nombre: 'Diego',
apellido: 'Martín',
edad: 30,
diHola: function(){
console.log("Hola");
}
};
Análogamente podemos especificar el método de una forma abreviada:
diHola(){...}
Podemos usar la palabra reservada this entro de un método para referir al propio objeto o a uno de sus atributos.
diHola(){
console.log(this.nombre);
}
El código anteior mostrará el contenido del atributo nombre del propio objeto, en este caso, ‘Diego’.
Estas funciones hacen algo cuando otra cosa termina. Por ejemplo, cuando pase un determinado tiempo o cuando un usuario lleve a cabo una acción.
Vamos a hacer una función callback cuando el usuario haga clic en un botón.
Para ello vamos a suponer que en el HTML tenemos un elemento button con con una clase .hazClic.
<button class="hazClic">Clic Aquí</button>
Y vamos a seleccionarlo con un método JS que permite buscar por selector CSS:
const button = document.querySelector(".hazClic");
A continuación vamos a agregarle un evento de clic mediante el método addEventListener(), el cual llama a otra función como callback.
function gestionarClic(){
console.log("Clic!!");
}
button.addEventListener('click',gestionarClic);
Fíjate que en este caso, no se llama a la función en el callback, sino que sólo se especifica el nombre de la función que será llamada cuando la otra finalice.
También podríamos usar una función anónima:
button.addEventListener('click',function(){
console.log("Click!!");
});
La etiqueta <noscript> nos permite especificar contenido alternativo para los usuarios sin JS en sus navegadores.
También tenemos el truco de comentar el contenido del script mediante un comentario HTML, que sólo surtirá efecto en un navegador que no interprete JavaScript.
<script> <!-- function mostrarMsj() { alert("Hola") } //--> </script>
DOM, de Document Object Model, son una serie de objetos con sus respectivos métodos y atributos, que tenemos a nuestra disposición para manipular todos los elementos que guardan relación con la experiencia de navegación del usuario. La ventana, el navegador, los elementos HTML, etc.
Aquí podemos ver la referencia del DOM en W3Schools.
Veamos algunos ejemplos:
Mediante el objeto document y sus métodos podemos realizar manipulación de los elementos del DOM, es decir, el contenido HTML de nuestra página.
Los métodos de selección nos sirven para acceder a los alementos que ya existen en el DOM de la página con la que trabajamos, es decir, todos los elementos HTML.
Veamos un primer ejemplo:
const p = document.querySelector('p')
Con el método querySelector() obtenemos el primer elemento que coincida con el selector CSS que hayamos introducido como parámetro. En el ejemplo, el primer párrafo.
La obtención de elementos es el primer paso para luego poder realizar cambios en el contenido de la página en función de eventos del usuario.
Con el método querySelectorAll() obtenemos todos los elementos que coincidan con el selector indicado.
const divs = document.querySelectorAll('div')
Con el ejemplo anterior obtenemos una lista de nodos, similar a un Array, que vamos a ver en detalle más adelante.
Podemos ser mucho más precisos mediante el uso de selectores más avanzados como los div que tengan asignada la clase menu con div.menu como parámetro de la función.
Si quieres hacer memoria sobre selectores CSS echa un ojo aquí.
Una funcionalidad muy útil es que podemos buscar elementos que estén dentro de elementos que ya hayamos seleccionado.
const div2 = document.querySelector("div");
div2.querySelector('p');
Adicionalmente existen otras formas de seleccionar elementos del documento, pero desde que existen estos que hemos visto, los demás son menos útiles o completos. En el siguiente artículo tienes un estupendo resumen de los mismos con ejemplos.
Si hemos mirado en la consola el contenido de alguna de las variables en las que hemos almacenado el elemento seleccionado habremos notado que obtenemos la etiqueta entera, que además es un objeto, por tanto, trae consigo muchas funcionalidades que podemos ver si ejecutamos console.dir(), que nos sacará un listado de todos los métodos y atributos disponibles.
Si analizamos un poco la lista veremos que podemos obtener cosas como el elemento padre, hijo, el contenido en texto, etc.
div2.textContent
Con el ejemplo anterior obtenemos el contenido en texto del div seleccionado. Pero igual que podemos obtener el contenido, también podemos actualizarlo simplemente con una nueva asignación.
div2.textContent = "nuevo contenido";
Con textContent obtenemos el contenido en forma de texto, incluyendo eqtiquetas de estilo que pueda contener. Existe otro similar que sólo obtiene el contenido legible, llamado innerText.
Podemos visualizar o listar fácilmente las clases que tienen un elemento del documento HTML asignadas con classList.
Supongamos este código HTML
<img class="preparar efecto" src="https://picsum.photos/400">
Si seleccionamos la imagen desde JS, podemos llamar al atributo classList para visualizar sus clases, así como para observar otros métodos útiles que contiene el prototipo.
const imagen = document.querySelector('.preparar');
console.log(imagen.classList);
Como podemos observar en la captura anterior, en la parte inferior se ven algunos métodos como add(). Con este podemos agregar nuevas clases al elemento.
imagen.classList.add('abrir');
Si volvemos a consultar el listado de clases, veremos que ahora la imagen tiene también la nueva clase asignada.
También tenemos el método remove() para eliminar clases o toggle() para intercambiar. Si no la tiene, la pone y si la tiene, la quita.
Agrega ahora estos estilos al documento:
<style> img{ transition: all 0.2s; } .redondear { border-radius: 50%; } </style>
Ahora podemos ejecutar toggle() una y otra vez en la consola para observar el cambio con la transición de borde redondeado de la clase redondear:
imagen.classList.toggle('redondear');
Con JavaScript podemos acceder fácilmente a cualquier atributo de un elemento del documento HTML llamándolo por su nombre como si de un atributo de un objeto se tratara.
Siguiendo con el ejemplo de la imagen anterior, podríamos acceder al atributo atl con imagen.alt o modificar o consultar su anchura con imagen.width.
imagen.alt = "Texto alternativo";
console.log("imagen.alt");
imagen.width = 200;
También disponemos de métodos para hacer lo mismo, getAttribute() y setAttribute(). Veamos un ejemplo:
imagen.getAttribute('alt');
imagen.setAttribute('alt','Nuevo texto alternativo');
Podemos crear elementos nuevos en el documento HTML con el método createElement(), el cual le pasamos como parámetro la etiqueta del elemento a crear.
const miParrafo = document.createElement('p');
Después, operamos con el nuevo elemento como si de cualquier otro se tratara.
miParrafo.classList.add('clase');
miParrafo.textContent = 'Soy un párrafo nuevo';
console.log(miParrafo);
Bien, con esto hemos efectivamente creado el elemento, pero, ¿por qué no aparece en la página?
Para que aparezca en el documento HTML debemos agregarlo como hijo de otro elemento que seleccionemos mediante el métido appendChild().
Como excepción, podemos acceder al body del documento directamente con document.body, sin necesidad de seleccionarlo previamente. De modo que podemos ejecutar
document.body.appendChild(miParrafo);
Esto inyectará el párrado en el DOM, al final del body.
Vamos a agregar ahora también una imagen y una caja contenedora. Primero crearemos los elementos.
const miImg = document.createElement('img');
miImg.src = "https://picsum.photos/200";
miImg.alt = "Texto Alternativo";
const miCaja = document.createElement('div');
miCaja.classList.add('contenedor');
miCaja.textContent = 'Soy un párrafo nuevo';
Y a continuación los agregamos al documento:
miCaja.appendChild(miImg);
miCaja.appendChild(miParrafo);
document.body.appendChild(miCaja);
Observa que primero hemos agregado el párrafo y la imagen al div y después incluimos la caja al body. Hasta que no la agregamos al body no se pintará en la página. Lo hacemos así para que el navegador sólo tenga que volver a pintar el contenido una vez en lugar de tres.
Existen otro métodos como append() o insertAdjacentElement(), que nos permite oncluir elementos en otros lugares que no son como último hijo de un elemento.
Otra forma muy cómoda de trabajar con elementos HTML es mediante strings con la comilla trasera o back slash, en la que fácilmente podemos interpolar también variables.
En esta ocasión trabajaremos con el atrobuto innerHTML.
Lo que hay que tener en cuenta con este método es que no se crean como objetos independientes dentro del DOM, hasta que no lo incluimos en él mediante el innerHTML y aún así luego tendríamos que selecccionarlos de nuevo.
Este problema se puede solucionar con los siguientes métodos:
const miFragmento = document.createRange()
.createContextualFragment(miHTML);
document.body.append(miFragmento);
El problema de estos dos últimos métodos en los que insertamos strings completas con código es que si pedimos datos a usuarios que se incluyan de forma automática en nuestro DOM, nos pueden meter scrips, lo que se conoce como XSS, Cross Site Scripting.
Se trata de un sencillo ejemplo que muestra los valores de la pantalla activa del usuario en el documento HTML:
<script>
document.write('Valores de las propiedades del objeto screen:<br>');
document.write('availHeight :' + screen.availHeight + '<br>');
document.write('availWidth :' + screen.availWidth + '<br>');
document.write('height :' + screen.height + '<br>');
document.write('width :' + screen.width + '<br>');
document.write('colorDepth :' + screen.colorDepth);
</script>
En el ejemplo a continuación se abre una nueva ventana en la que agregamos código HTML mediante document.write. Es el uso habitual de este método.
<HTML>
<HEAD>
<TITLE>Abriendo y cerrando ventanas con Javascript vía Víctor M. Rivas Santos</TITLE>
<SCRIPT>
var nuevaVentana;
function nueva() {
nuevaVentana=window.open("", "segundaPag",
"toolbar=yes,location=no,menubar=yes,resizable=yes,"+
"width=30,height=30" );
nuevaVentana.document.write("<HTML><HEAD><TITLE>"+
"Sin Título</TITLE></HEAD>\n");
nuevaVentana.document.write("<BODY><form>\n");
nuevaVentana.document.write("<input type='button' "+
"value='Cerrar' onClick='window.close();'>\n");
nuevaVentana.document.write("</form>\n");
nuevaVentana.document.write("</BODY></HTML>\n");
nuevaVentana.document.close();
}
// -->
</SCRIPT>
<BODY>
<FORM>
<INPUT TYPE="button" VALUE="Abrir" onClick="nueva();"><br>
</FORM>
</BODY>
</HTML>
Este ejemplo aporta información sobre el navegador que está empleando el usuario.
<!-- Manual de JavaScript de WebEstilo -->
<HTML>
<HEAD>
<title>Ejemplo de JavaScript</title>
</HEAD>
<BODY>
<script LANGUAGE="JavaScript">
<!--
document.write("Navigator <b>appCodeName</b>: " + navigator.appCodeName + "<br>");
document.write("Navigator <b>appName</b>: " + navigator.appName + "<br>");
document.write("Navigator <b>appVersion</b>: " + navigator.appVersion + "<br>");
document.write("Navigator <b>language</b>: " + navigator.language + "<br>");
document.write("Navigator <b>platform</b>: " + navigator.platform + "<br>");
document.write("Navigator <b>userAgent</b>: " + navigator.userAgent + "<br>");
//-->
</script>
</BODY>
</HTML>
Este ejemplo muestra información sobre la URL y demás parámetros habituales del objeto Location:
<!-- Manual de JavaScript de WebEstilo -->
<HTML>
<HEAD>
<title>Ejemplo de JavaScript</title>
</HEAD>
<BODY>
<script LANGUAGE="JavaScript">
<!--
document.write("Location <b>href</b>: " + location.href + "<br>");
document.write("Location <b>host</b>: " + location.host + "<br>");
document.write("Location <b>hostname</b>: " + location.hostname + "<br>");
document.write("Location <b>pathname</b>: " + location.pathname + "<br>");
document.write("Location <b>port</b>: " + location.port + "<br>");
document.write("Location <b>protocol</b>: " + location.protocol + "<br>");
//-->
</script>
</BODY>
</HTML>
Para trabajar con fechas tenemos el objeto Date. Es importante considerar que JS trabaja la fecha en milisegundos, así que debemos hacer cálculos para verlo de forma más entendible.
Date.now();//devuelve la fecha actual en ms
Existen conversores para poderlo entender mejor, como epoch.vercel.app
Cálculo de los días entre la fecha actual y una fecha futura:
<script>
var hoy = new Date();
var otraFecha = new Date(2020,12,31);
//A continuación obtenemos la diferencia en milisegundos
var diferencia = otraFecha.getTime() - hoy.getTime();
//Cálculo de días que hay en los milisegundos redondeando
dias = Math.round(diferencia/(1000*60*60*24));
document.write("Faltan " + dias + " días");
</script>
Ejemplos con Arrays:
También se pueden declarar los arrays como objetos:
var persona = {nombre:"John", apellido:"Snow", edad:46};
Y estar compuestas por objetos:
miArray[0] = Date.now;
miArray[1] = miFuncion;
También podemos recorrer arrays con la función forEach().
En los ejemplos anteriores se puede ver cómo en algunos casos de usa la llamada al constructor de la clase Array y en otros no. En W3Schools, sección When to Use Arrays. When to use Objects en la página JavaScript Arrays podemos ver los matices.
Una de las cosas básicas que como vemos, ya tenemos implementado en JavaScript a cerca de las matrices de elementos es su búsqueda y ordenación.
Veamos algunos recursos sobre esto a nivel teórico:
Analiza el siguiente ejemplo y descubre, buscando información externa, qué hacen los métodos shift y unshift.
¿Podrías determinar el número de elementos del array si agregamos las siguientes líneas de código al script?
countries.splice(3,0, 'Austria', 'México', 'Panamá');
document.write('<p>El lugar más imperial es <em>');
document.write(countries[3] + '</em></p>');
countries.splice(6,1);
document.write('<p>El lugar en que más me he cansado es <em>');
document.write(countries[6] + '</em></p>');
countries.splice(1,2, 'Canadá', 'Egipto');
document.write('<p>El lugar que más me ha impactado es <em>');
document.write(countries[1] + '</em></p>');
Ahora prueba a ordenar y mostrar el array.
Es importante recordar que la ordenación de números se puede hacer mediante la función que vemos en el siguiente ejemplo:
var numArray = [140000, 104, 99];
numArray = numArray.sort(function (a, b) { return a - b; });
Podemos meter Arrays dentro de otras, generando así matrices de múltiples dimensiones.
Se explican paso a paso en el artículo Arrays multidimensionales en Javascript de Miguel Ángel Álvarez.
En este script tenemos en un ejemplo:
var arrayMuchasDimensiones = [1, ["hola", "que", "tal", ["estas", "estamos", "estoy"], ["bien", "mal"], "acabo"], 2, 5];
alert (arrayMuchasDimensiones[0]);
alert (arrayMuchasDimensiones[1][2]);
alert (arrayMuchasDimensiones[1][3][1]);
alert (arrayMuchasDimensiones[1][3]);
Se propone realizar un script en el que carguemos preguntas y respuestas en un Array bidimensional y posteriormente vaya haciendo las preguntas al usuario mediante promt e indique si la respuesta es correcta o no. Si la respuesta no es correcta, indicará la respuesta correcta.
Los eventos en JavaScript son pieza fundamental. Nos sirven para hacer más completa la experiencia de usuario teniendo en cuenta lo que este hace. Digamos que mediante la gestión de eventos prepararemos a los elementos HTML que queramos para que cambien en función de las acciones del usuario.
De esta forma, podemos hacer cosas como cambiar el contenido de la web en función de si el usuario hace clic en algún botón, pulsa una tecla, hace scroll o simplemente carga una página.
Podemos agregar eventos a nuestros elementos HTML con el método addEventListener(“evento”, callback) en el que como se puede observar, disponemos de 2 parámetros de entrada, uno para especificar el evento y otro para indicar la función que será llamada en el momento en que se dispare el evento.
const boton = document.getElementById("boton");
function cambiarFontSize() {
this.style.fontSize = "45px";
}
boton.addEventListener("click", cambiarFontSize);
En el ejemplo anterior, seleccionamos un elemento del documento, creamos una función y después asignamos un evento de tipo clic al elemento seleccionado, que llamará a la función indicada cuando hagamos clic sobre el botón.
Fíjate en la función no lleva los paréntesis en el callback. Esto es porque esa función no la invocamos nosotros en el momento presente, sino que será invocada por el navegador cuando suceda el evento de clic.
Con removeEventListener() podemos eliminar eventos que hayamos activado previamente.
MDN JavaScript Guide: MDN ofrece una guía detallada sobre JavaScript, que incluye información sobre cómo documentar código JavaScript de manera efectiva.
Un libro recomendado es Clean Code (código limpio en español). Y este un repo de Github recomendado basado en el libro y adaptado a JS.
mas informacion sobre paginas web con JavaScript
Hola Alejandro. Gracias por comentar. ¿Puedes ser más concreto en tu consulta? De todas formas estoy actualizando activamente este artículo. Permanece atento a las ampliaciones que le hago.
Saludos,
Diego