Javascript#2
Segunda parte
VAMOS A IR APRENDIENDO LOS CONCEPTOS SIGUIENDO VARIOS EJEMPLOS
Piedra, papel o tijera
Problema
Vamos a hacer una app para jugar contra la “computadora” al piedra, papel o tijera.
Creemos un botón, que al apretarlo “simule” la inteligencia de una persona y elija automáticamente una de las tres opciones.
Resolver el problema
¿Qué vamos a aprender?
¿Cómo vamos a “simular” que la computadora elija una de las tres opciones disponibles?
La idea es elegir al azar una de las tres opciones del juego:
Podríamos generar un número al azar y hacer 3 if (o un switch) para saber que opción elegir.
Contra: Si bien tenemos tres opciones puede haber variantes con más opciones. Se hace muy largo el código.
Solución: Hagamos un código que elija al azar de una lista de opciones, sean 3 o la cantidad que sean.
5 opciones
Arreglos
VARIABLE SIMPLES
ARREGLO
Los arreglos almacenan elementos en una colección de datos ordenados.
Son una variable que tiene muchas posiciones.
En lugar de una caja, ahora tenemos una cajonera.
“Juan”
nombre
Declarar arreglos
// declarar un arreglo vacío
let names = [];
// declarar arreglo con tres elementos
let cars = ["Saab", "Volvo", "BMW"];
names
"Saab" | "Volvo" | "BMW" |
cars
no tiene posiciones
tiene 3 posiciones (0, 1, 2)
0
1
2
Arreglos - Acceso
Acceder a un arreglo
Los elementos se acceden por índice (comienzan en 0).
let cars = ["Saab", "Volvo", "BMW"];
let car = cars[0];
//cars es un arreglo, car es un texto
console.log(car); // “Saab”
console.log(cars[1]); // “Volvo”
console.log(cars[2]); // “BWM”
"Saab"
"Saab" | "Volvo" | "BMW" |
car
cars
0
1
2
Tamaño de un arreglo
let frutas = ["manzana", "pera", "naranja"];��Cantidad de elementos�frutas.length; // 3�
Resolviendo el problema
Creo un arreglo para almacenar la lista de opciones que tiene la computadora para elegir.
let opciones = [“piedra”, “papel”, “tijera”];
Ejecutó un numero random entre 0 y 2 para elegir al “azar” una de las opciones.
Random
Math.floor();
Que redondea al menor entero
Math.floor((Math.random() * 6) + 1);
0 < Math.random() * 6 < 5.999
En este caso tenemos 3 opciones, o mejor aún opciones.length opciones
REPASO
Como los arreglos empiezan en 0 no hace falta sumar 1
Solución
"use strict"
let btn = document.querySelector('#btn-play');
btn.addEventListener('click', jugar);
// arreglo con todas las opciones posibles
let opciones = ['piedra', 'papel', 'tijera'];
function jugar() {
// numero random entre 0 y el tamaño del arreglo
let random = Math.floor((Math.random() * opciones.length));
let opcion = opciones[random];
// escribimos el resultado en el html
document.querySelector('.result').innerHTML = opcion;
}
Resumen
Aprendimos
Aplicación de sorteos
Problema
El piedra/papel/tijera fue un éxito. Así que nos contrataron para hacer otra app.
Tenemos que hacer una app para hacer sorteos donde podamos agregar todas las personas que queramos y nos de un ganador.
Creemos un formulario y una lista vacía para ir completando con lo que carga el usuario. Además tiene que tener un botón de reset.
Resolver el problema
¿Qué vamos a aprender?
Modelo vs Vista
¿Por qué necesito un arreglo si puedo ir insertando los nombres directo en el HTML?
No es responsabilidad del DOM guardar los datos, sólo mostrarlos!
Modelo vs Vista
Al aumentar la complejidad de mi aplicación, es casi obligatorio guardar el estado de los datos en Javascript, y luego representarlo (dibujarlo/escribirlo) en el DOM.
Las variables en Javascript son nuestro “modelo” de datos y después se muestra en el DOM, llamado vista .
Mati |
Franco |
Nacho |
Javi |
Los usuarios a sortear son:
Arreglo en JS, más fácil de modificar
Lista en el HTML generada desde el arreglo
Agregando elementos y borrando
let frutas = ["manzana", "pera", "naranja"];��Cantidad de elementos�frutas.length;�
Agregar un elemento al final�frutas.push("mandarina");��Borrar último elemento
frutas.pop();
Vaciar el arreglo
frutas = [];
Recorriendo Arreglos
let arr = [1,2,3]
// foreach de ES6�for (let elem of arr) { // 1, 2, 3� console.log(elem);�}
// método clásico�for (let i=0; i<arr.length; i++) { // 1, 2, 3� let elem = arr[i];� console.log(elem);
}
Resolviendo el problema
Creo un arreglo para almacenar la lista de personas que ingresa el usuario.
“Mati” |
“Franco” |
“Nacho” |
“Javi” |
“Otro nombre” |
let personas = [];
0
1
2
3
4
5
Resolviendo el problema
Creo 3 botones (Agregar, Limpiar todos, Borrar ultimo), 1 input para agregar nombres
Creo funciones agregar(), reset(), borrarUltimo() y mostrar()
Llamo a mostrar cada vez que se modifica el arreglo.
Solución
function sortear() {
let pos = Math.floor(
Math.random()*nombres.length);
let g = document.querySelector("#ganador");
g.innerHTML = nombres[pos];
}
let nombres = [];
function agregar() {
let nombre = document.getElementById("nombre").value;
nombres.push(nombre);
mostrar();
}
function reset() {
nombres = [];
mostrar();
}
function mostrar() {
let lista = document.querySelector("#listado");
lista.innerHTML = ""; //borro todo lo que haya
for(let n of nombres){
lista.innerHTML += `<li>${n}</li>`;
//lista.innerHTML = lista.innerHTML + "<li>" + n + "</li>";
}
} //...los event listener
function borrarUltimo() {
nombres.pop();
mostrar();
}
variable global para el estado (el modelo)
una función por evento
una función para evitar duplicar código en cada evento
generamos HTML desde JS
el sorteo es igual
Resumen
Aprendimos
Variables globales y DOMContentLoaded
Variables Globales
Como la variable contador es global, se puede acceder desde cualquier lado de la aplicación. Incluso se puede ver o modificar desde la consola del navegador!
Esto no es bueno, incluso dos programas JS podrían usar el mismo nombre de variable y entonces la compartirán sin saberlo.
console.log(contador);
contador = contador + 1000;
console.log(contador);
Evitar variables y funciones globales
Otra forma de hacerlo
Podemos configurar todos los eventos una vez que ya se cargo el DOM. De este modo nos aseguramos que estén cargados todos los elementos del DOM antes de manipularlos
document.addEventListener("DOMContentLoaded",
iniciarPagina);
function iniciarPagina(){
// código de inicialización de eventos
}
Evitar variables y funciones globales
document.addEventListener('DOMContentLoaded', iniciarContador);
function iniciarContador() {
"use strict";
let btn = document.getElementById("btn-click");
btn.addEventListener("click", sumar);
let contador = 0;
function sumar() {
//incrementa el valor de contador
contador++;
//es lo mismo que contador = contador + 1
let valor = document.getElementById("spanContador");
valor.innerHTML = contador;
}
}
leo variables de afuera, no de más adentro
“contador” no puede usarse desde más afuera
Resumen
Aprendimos a
App Contador de Pasos
Contador de pasos
Queremos realizar una app que lleve la cuenta de la cantidad de pasos que realizo por día:
¿Qué vamos a aprender?
Tipos de Datos
Las variables pueden tener tipos:
Tipado de Variables - Tipos
El tipado estático nos obliga a definir desde el principio el tipo de una variable. Lenguajes con tipado estático son C++, Java, C# (casi) entre otros.
El tipado dinámico nos da la facilidad de no definir los tipos al declarar una variable, algunos ejemplos son PHP, JavaScript, Grooby, Phyton, entre otros.
¿Se les ocurren pros y contras?
Tipos
Javascript tiene tipos dinámicos.
let nombre = "Pepe"; //nombre es un string
…
nombre = 2; //nombre es un int (cambia tipo)
Mala práctica
Conversión de tipos
5 == "5" //true
"1" + 2 + 3; //"123"
//Conversion manual de tipos�parseInt("1", 10) + 2 + 3; //6
'<p>Vos sos '+nombre+' '+apellido+'.</p>'
`<p>Vos sos ${nombre} ${apellido}.</p>`
Undefined
Escribiendo código JavaScript más limpio
Parámetros
Podemos hacer el código más genérico y reutilizable utilizando parámetros y devolviendo valores.
Ejemplo:
// función específica para sumar 2 + 4
function sumarDosMasCuatro {
let suma = 2 + 4;
console.log(suma);
}
--------------
// función genérica para sumar dos valores cualquiera
function sumar(parametro1, parametro2) {
return parametro1 + parametro2;
}
// la llamamos con los valores que queremos
let resultado = sumar(2, 8); //devuelve 10
console.log(resultado);
El primer parámetro va a valer 2, el segundo va a valer 8, por lo que la suma dará 10
Los parámetros son la entrada del código, y el valor que devuelve es la salida.
Funciones anónimas
Se usan para no crear tantas funciones que se usan en un solo lugar
btn.addEventListener("click", sumar(20,50));
btn.addEventListener("click", function(){
let valor1 = 20;
let valor2 = 50;
let resultado = sumar(valor1, valor2)
});
Declaramos una función anónima, para poder llamar a una función con parámetros
Resolver el problema
<button id="btn-decrementar">-</button>
<button id="btn-incrementar">+</button>
<button id="btn-agregar">AGREGAR</button>
Asignar eventos a los 3 botones
document.querySelector('#btn-incrementar').addEventListener('click', function(e) {
incrementar(1)
});
document.querySelector('#btn-decrementar').addEventListener('click', function(e) {
incrementar(-1);
});
document.querySelector('#btn-agregar').addEventListener('click', incrementarManual);
JS + Función anónima:
Resumen
Aprendimos
Reloj
Reloj - Bomba
Simular la cuenta regresiva de una bomba.
Con un botón activarla y dejar 5 segundos para escapar y comenzar la cuenta regresiva.
El valor de la cuenta regresiva se ingresa por un input
Qué vamos a aprender
Qué vamos a aprender?
Eventos de tiempo
Se puede programar un evento, para ejecutar una función dentro de M milisegundos.
//dispara (ejecuta bang) en 5 segundos
let timer = setTimeout(bang, 5000);
Eventos de tiempo
let timer = setInterval(clock, 1000);
…
clearInterval(timer);
setInterval llama a la función cada 1000 milisegundos, hasta que se limpie el intervalo.
Resultado
Cuenta Regresiva
function cuentaRegre(){� let intervalo = setInterval(function() {� if (i === 0) {� clearInterval(intervalo); // limpio intervalo� alert('BOOOOOM!!');� }� else {� i--;� }� }, 1000);�}
Implicancias de eventos de tiempo
[TBC]
Resumen
Aprendimos
Javascript - Buenas prácticas
Separar los "event handlers"
// Mal hecho function handleClick(event){ let popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } // Mejor, pero sigue estando mal function handleClick(event){ showPopup(event); } function showPopup(event){ let popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } | // La solucion correcta function handleClick(event){ showPopup(event.clientX, event.clientY); } function showPopup(x, y){ let popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } |
Usar Cache de Selectores
Las consultas al DOM son MUY lentas.
Editarlo también.
Usar Cache de Selectores
function sinCache () { let i, val; for(i=0; i<50; i++){ val = document.getElementById('title').innerHTML } } | function conCache (){ let i, val; let h1 = document.getElementById('title'); for(i=0; i<50; i++){ val = h1.innerHTML; } } |
JS y sus detalles
Obtener nodos del DOM
Retorna un nodo
let elem = document.getElementById("identificador");
let singleElem = document.querySelector(".myclass");
Retorna uno o más
let manyElements = document.getElementsByClassName("myclass");�let manyElems = document.querySelectorAll(".myclass");
Más info https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
sin el punto
Selector de CSS
Comparaciones cortas en JS
?
let tmp = (bool) ? 1 : 2
es igual que
let tmp = 0;
if(bool)
tmp=1;
else
tmp=2;
Falsey evaluation
En Javascript, hay diferentes cosas que al convertirla a bool, se transforma a false automáticamente.
null == undefined == 0 == false == ""
No es tan así, pero es una buena simplificación.
let a = null; let b; //undefined
let c = 0; let d = false;
let e = "";
if (a), if (b), if (c), if (d), if (e) //false
Puedo pasarme horas revisando un bug en una comparación, que era por un undefined en la variable.
Falsey Evaluation
Largo de una cadena
Existen muchas funciones que ya trae Javascript
Para calcular el largo de una cadena puedo usar:
let largo = str.length("cadena");
El valor calculado se devuelve y debe guardarse en una variable
Ejercicios
Ejercicios
Ejercicio #1
Ejercicio #2
AHORA LES TOCA PRACTICAR :D
Más Información
Libros
O'Reilly “You don’t know JS, up going”
Eventos
O'Reilly “You don’t know JS, ES6 and beyond”
https://github.com/getify/You-Dont-Know-JS/tree/master/es6%20%26%20beyond