Libro Js

October 1, 2017 | Author: Jehú Guillén | Category: Java Script, Computer Program, Compiler, Division (Mathematics), Programming Language
Share Embed Donate


Short Description

Descripción: javascript...

Description

Introducción a la programación con javascript desde cero.

Versión 0.47

Temario 1. Introducción 1. Motivación 2. Requerimientos básicos 3. Breve historia de javascript 4. ¿Cómo sacarle provecho al libro? 5. Lenguajes de programación interpretados 2. Herramientas 1. El inspector de elementos 2. El editor de texto 3. Variables 1. Declaraciones y asignaciones 2. Memoria Dinámica 3. Comentarios 4. Tipos de datos 4. Operadores 1. Operadores aritméticos 2. Operadores de asignación 3. Operadores lógicos 5. Condiciones 1. If, else if, else 2. Ifs anidados 3. Lógica booleana 4. Operador ternario 6. Ciclos 1. For 2. While 3. Do While 4. Validación de entradas 5. Break, continue

7. Ciclos anidados 8. Funciones 1. Introducción a funciones 2. Definición 3. Nombres 4. Retorno 5. Parámetros 6. Ambito o Scope de las variables 7. Funciones de primera clase 8. Funciones anónimas 9. Arrays 1. Métodos comunes 2. Mutabilidad 3. Métodos útiles pero no 100% soportados 4. Lowdash y underscore 5. Copia de arrays 10. Objetos 1. Objetos literales 2. Agregando propiedades a un objeto. 3. El operador this 4. El objeto Window 11. Funciones avanzada 1. Funciones autoejecutables 2. Funciones recursivas 3. Closures 4. Patrón Módulo 12. Los prototipos 1. Función constructora 2. Prototupis 13. Javascript y HTML 1. Estructura de un proyecto web 2. El objeto document

3. Encontrando elementos HTML (id, tag o clase) 4. InnerHTML 14. Eventos en javascript 1. Manejando eventos 2. El evento onClick 3. El evento onChange 4. El evento onInput 5. window.load 6. Bubbling 15. Formularios. 1. El evento onSubmit 2. Regex 16. Ajax 1. XMLHttpRequest object 2. Métodos GET / POST 3. JSON 17. Introducción a jQuery 1. $() 2. Selectores 3. Traversing 18. Eventos en Jquery 1. Eventos 2. Document ready 19. Ajax con Jquery

Capítulo 1

Introducción. Motivación Difícilmente existe un lenguaje más importante para la programación de sitios web que Javascript, según w3techs Javascript es utilizado en el 89.9% de los sitios web del mundo y no existe ningún indicio de que esta tendencia vaya a disminuir en el mediano plazo. Este libro busca entregar las bases para entender y poder utilizar javascript para la construcción de sitios web interactivos.

¿Es este libro para mi? Si has construido páginas web previamente y copiaste y pegaste javascript dentro del sitio sin entenderlo, este libro es para ti, para que entiendas como funciona javascript y tengas las herramientas para modificar los scripts que copias y crear tus propios script. Si ya tienes experiencia con javascript pero no eres un experto puedes partir desde el capítulo 8.

Requerimientos básicos Para seguir este libro se necesitan conocimientos básicos de HTML y CSS. Conocimientos previos de programación son deseables pero no estrictamente necesarios.

Breve historia de javascript Javascript, comúnmente abreviado como JS, es un lenguaje de programación inventado por Brendan Eich en Netscape en 1995. Este lenguaje tiene el honor de ser uno de los más extendidos del mundo, se encuentra en la mayoría de los sitios web, y también, gracias a nuevas implementaciones como node.js, es posible utilizar javascript del lado del

servidor e incluso para construir aplicaciones para escritorio. De las características del lenguaje cabe destacar que orientado a objetos, basado en prototipos, funcional e imperativo y de tipeo débil, si todavía no sabes que son todas estas cosas no te preocupes las estudiaremos a continuación.

¿Cómo sacarle el máximo provecho al libro? Cada capítulo tiene una sección de preguntas, esas preguntas no son complejas y es posible contestarlas únicamente con compresión de lectura de este libro, se recomienda no dejar ninguna pregunta sin contestar. Este libro se ha escrito sin rodeos, los capítulos son cortos y van directo a lo importante. Antes de empezar a hablar de Javascript es necesario hacer una pequeña mención de como funcionan los lenguajes de programación, esto nos ayudará a obtener los mapas mentales necesarios para entender como funciona javascript y poder escribir nuestros códigos.

Cómo la computadora es capaz de entender un lenguaje de programación? Una computadora no funciona muy distinto a una calculadora, toda computadora tiene un set de instrucciones que es capaz de seguir, esas instrucciones son del tipo, sumar, restar, mover bits, mover tal cosa a tal punto de la memoria, etc … Los programadores no pueden escribir directamente esas instrucciones puesto que para que las entienda tienen que estar escritas en lenguaje máquina, entonces lo que se hace es escribir un código fuente en un lenguaje de programación y para que un computador pueda entender un set de instrucciones en el lenguaje escrito tiene que ocurrir una de dos cosas. 1) El programa escrito debe poder transformarse de forma previa a lenguaje máquina, a este proceso se le conoce como compilación, o … 2) El código fuente debe poder ser interpretado en tiempo real y ese interprete convierte las instrucciones a lenguaje máquina.

Programas compilados Si alguna vez has visto un archivo de extensión .exe claramente has visto un programa compilado, ahora no sólo existen para Windows, existen para casi todas los sistemas operativos.

Compilar el programa previamente vs interpretarlo en tiempo real tiene múltiples ventajas, una de ellas es el la velocidad de ejecución, pero eso no quiere decir que siempre sea la mejor forma. La desventaja de este proceso es que cada máquina es distinta y se requiere compilar un programa para cada máquina distinta o con sistema operativo distinto.

Programas interpretados Interpretar un programa requiere de un interprete que recibe el nombre de cliente y es capaz de traducir en tiempo real el código escrito por una persona a lenguaje máquina. La ventaja de los programas interpretados es que si existe el interprete para la plataforma tu programa correrá en esa plataforma. La desventaja es que será más lento que un programa compilado.

Javascript Javascript es uno de los lenguajes interpretados más famosos del mundo y con una gran ventaja por sobre otros lenguajes interpretados, el interpretador es el navegador y por lo tanto no requiere que el usuario instale ningún programa especial para ejecutar los códigos enviados, haciéndolo un muy buen lenguaje de programación multiplataforma especialmente para la web. Los programas escritos en javascript pueden ser leídos directamente en el navegador, cabe señalar que si se pueden hacer programas en javascript para escritorio o para servidores, estos tema no lo discutiremos en este libro pero puedes aprender más sobre javascript para lado servidor o para programas de escritorio buscando sobre node.js

Preguntas ¿Para qué sirve Javascript? ¿Cuáles son las diferencia entre un programa compilado y uno interpretado. ¿Javascript es interpretado o se compila? ¿Qué es el código fuente? ¿Qué programa lee Javascript?

Capítulo 2

Herramientas El inspector de elementos Para apoyar el desarrollo de proyectos en Javascript muchos navegadores como Chrome o Mozilla Firefox tienen inspectores de elementos, este inspector permite revisar paso a paso las instrucciones que está corriendo Javascript y poder investigar las causas de errores. Al proceso de investigar y eliminar errores se le denomina debugging (de-bug), En Chrome podemos abrir el inspector de elementos con un click derecho y seleccionando la opción inspector de elementos y luego seleccionando el tab console.

Otra opción para abrir la consola de javascript es en la barra de tareas view >> developer >> javascript console La consola de javascript permite ejecutar directamente código javascript en el navegador, la primera sección de este libre puede ser probada directamente de esta forma sin necesidad de un editor de texto.

Modo network Dentro del inspector de elementos trabajaremos principalmente con el tab Console pero el tab Network nos servirá también para aprender un poco más sobre javascript en la web. Si abrimos el tab network y luego entramos en una página (tiene que ser en ese orden, si lo abrimos después no funciona y hay que recargar la página) observaremos que todos los archivos que nos envía un servidor, esos archivos serán el HTML, muchos archivos CSS y muchos archivos JS y además imágenes.

Modo código fuente Es muy importante tener en cuenta que cuando un servidor envía una página web envía todos los códigos, tanto los HTML, los CSS y los JS, por lo tanto no tiene sentido ocultar una password en un javascript, porque puede ser visto y fácilmente hackeado. Además es posible ver el código fuente de cualquier página web, basta que entres, vayas a view->developer->view source y podrás clonar el front-end de cualquier página web.

El inspector de elementos será uno de tus mejores amigos durante el desarrollo de un script, nos permite hacer pruebas rápida y debugging del proceso.

¿Qué es el desarrollo de front-end? El desarrollo web front-end tiene 3 capas que consisten en la construcción de HTML, CSS y JS, la imagen a continuación ilustra.

Con javascript podemos: 1. Realizar cálculos matemáticos 2. Operar sobre el HTML y CSS cambiando sus propiedades 3. hacer llamados asíncronos a un servidor sin tener que recargar la página. Todo lo anterior le dará interactividad a la página.

¿Cómo protejo mi página? No puedes, por lo menos no en el sentido de no enviar la página web, es posible ofuscar el código web, o sea hacerlo ilegible al ojo humano, pero no es de mucho ayuda y es un proceso reversible además que puede generar complicaciones con algunos scripts de javascript. Lo importante es entender que sólo se puede copiar el front, o sea puedes copiar todo el estilo e imágenes de Facebook, pero sólo lo que cargaste, no tienes acceso a los datos y al como se maneja la lógica de esos datos.

A los programadores de estas secciones se les conoce como programadores back-end.

El editor de texto A pesar de que a través de la consola del navegador podemos ejecutar directamente código javascript, esta forma no nos permite poder guardar nuestros códigos y más adelante compartirlos o utilizarlos en nuestro proyecto. Para escribir javascript podemos crear un archivo .js y poner todo el código dentro del archivo, o podemos crear un archivo html y dentro de la etiqueta escribir nuestros códigos. Para escribir los códigos podemos ocupar un editor rústico como el famoso block de notas de windows, pero es mejor ocupar un editor con resaltado de sintaxis y con autocompletado que nos ayude a trabajar mejor y más rápido. Por lo mismo se recomienda utilizar los editor de sublime text 3 o Atom, ambos muy buenos y potentes.

Mi primer javascript Podemos crear nuestro primer proyecto javascript dentro de un archivo HTML. Para eso abriremos el editor de texto crearemos un archivo llamado miprimerjs.html y luego dentro escribiremos:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

alert("hola");

Finalmente abriremos el archivo con el navegador para observar los resultados.

Alert es una función incorporada en javascript que permite levantar un popup bien molesto que interrumpe al usuario diciéndole "hola", no es bueno utilizarla para la construcción de un sitio web pero es la técnica más rudimentaria para debugging. Otra opción en lugar de ocupar alert consiste en ocupar console.log, esta permite mostrar dentro del tab console del inspector de elementos el output esperado. O sea el código:

1 2 3

console.log("hola mundo");

Mostraría hola mundo. A partir de ahora el lector es libre de copiar los códigos de javascript dentro de las etiquetas script o puede ejecutarlo directamente en el tab console del navegador de chrome o firefox. Lo segundo es más fácil de probar pero no dejará un registro claro de lo que haya hecho y los apuntes podrían ser valiosos para repasar.

Preguntas ¿Cuál es la diferencia entre un desarrollador back y uno front? ¿Para qué sirve el tab console del inspector de elementos? ¿Para qué sirve el modo network?

Desafío Utiliza lo aprendido en este capítulo para copiar una página web que te guste.

Capítulo 3

Variables: Las variables son contenedores para asignar o guardar datos, se les denomina variables puesto que estos contenedores pueden cambiar de contenido. A los contenedores que no pueden cambiar el contenido se les denomina constantes. Una variable tiene se compone de: Un identificador Un valor.

Declaraciones y Asignaciones de variables Cuando uno asigna el identificador a la variable se le llama declaración, un ejemplo de esto sería: var variable; y cuando uno les da un contenido se le llama asignación, la asignación de contenido se hace a través del operador = , por ejemplo:

1

var a = "Hola";

Una pregunta interesante sería, ¿Por qué Hola está envuelto en comillas? Esto se debe a que es un string, o sea una secuencia de caracteres que no es una variable y javascript lo necesita para poder diferenciarlo de un identificador, para entender esto mejor veamos el siguiente ejemplo:

1 2

var a = "Hola"; var b = a;

Como el identificador a tiene el valor de "Hola" al asignar b al valor de a, lo que estamos haciendo es decir que ahora b tendrá el valor de hola. Lo puedes probar tu mismo escribiendo console.log(b) Aquí descubrimos otra cosa, el código se lee linealmente, o sea primero javascript procesa el valor de a y luego el valor de b, de otra forma no sabría que b tiene el valor de "hola"

Además es importante destacar que una variable puede ser declarada sin una asignación, ejemplo de esto sería:

1

var sin_asignar;

Si ahora mostramos con console.log(sin_declarar) obtendremos como resultado undefined. Otra pregunta interesante sería ¿Qué sucedería si hacemos esto sobre algo que no esté declarado? ejemplo: console.log(no_definido) , en este caso obtendremos un error de una referencia no definida.

Preguntas: Antes de seguir avanzando en el libro deberías ser capaz de contestar las siguientes preguntas: ¿Cuál es la diferencia entre asignación y declaración? ¿Se puede asignar una variable sin declararla? ¿Se puede declarar una variable sin asignarla? ¿Cuál es la diferencia entre una variable y un string? ¿Que valor tiene una variable que no ha sido asignada?

Comentando el código Antes de seguir hablando de variables vamos a hacer una pausa para hablar de comentarios, Los comentarios son líneas de código que están en el código pero que no se ejecutan.

Se pueden hacer 2 tipos de comentarios, de una línea o de multiples líneas:

Comentarios de una línea 1 2

// Todo lo que se encuentra después de “//” no será ejecutado. console.log("ESTO SI SE EJECUTARA!")

Comentarios de múltiples líneas 1 2 3 4 5 6 7

/* Todo lo que se encuentre entre “/*” y “*/” no se ejecutará, pero lo que se encuentre antes de “/*” y después de “*/” si se ejecutará ejemplo: console.log("Esta línea NO se ejecuta)" */ console.log("Esta línea si se ejecuta")

Probando lo aprendido 1 2 3 4 5

var a = 2; /* a = 3 */ console.log(a)

¿Cuál será el output en la consola?, ¿2 o 3?

Tipos de datos En el capítulo anterior mencionamos que las variables eran contenedores de datos, estos contenedores no son genéricos, de hecho hay tipos de contenedores y dentro de estos se incluyen: 1. Number

2. String 3. Boolean 4. Array 5. Object

Numbers Number hace referencia a un número. Para guardar un número en una variable escribimos la instrucción:

1

var num = 2;

Donde se asignará el número 2 a la variable num. Podemos probar que esto efectivamente es así escribiendo console.log(typeof(num)); typeof(num) devuelve el tipo de dato del elemento pasado como argumento, o sea lo que está entre los paréntesis. En el caso anterior la respuesta será Number. Los decimales como 3.8 y los números negativos pertenecen también al tipo Number, es importante tener en cuenta que los números decimales ocupan el caracter punto como separador y no una coma.

String El tipo de dato String hace referencia a una cadena de caracteres o palabras, si queremos almacenar un String en una variable ejecutamos la instrucción:

1

var palabra = "Hola mundo";

Donde "Hola mundo" es el dato que se asigna a la variable "palabra". Notar que “Hola mundo” se encuentra entre comillas, esto quiere decir que este tipo de dato es un String. También podemos poner dentro de un string números, ejemplo var s = "Hola21" incluso podemos tener un string que sólo contenga un número, como por ejemplo var n = 20 . A simple vista no hay mucha diferencia, pero al momento de comenzar con las operaciones numéricas encontraremos comportamientos extraños si asignamos a un número como un String. Por lo que los números siempre los asignaremos sin comillas.

​Boolean Este tipo de dato hace referencia a un valor que puede ser verdadero o falso, o bien t​r ue ​o f​alse. ​Estas variables se utilizan por lo general como comparadores, o sea para verificar si se cumplen ciertas condiciones. Como por ejemplo "El usuario es mayor de edad?". Para asignar un tipo de dato Boolean a una variable basta con:

1 2

var positivo = true; var negativo = false;

Hay que destacar que en este caso no se utiliza comillas para true o false y la razón es sencilla, es porque no son Strings, son palabras reservadas de javascript para indicar los valores booleanos.

Array Los Array son contenedores para múltiples datos, un array puede contener distintos tipos de datos, incluso mezclados!, lo que puede eventualmente generar una confusión. Un arreglo puede contener Number, String, Boolean, Object e incluso otros Array. Para definir un array:

1

var arreglo = [];

El paréntesis de corchete indica a javascript que cree un arreglo vacío. También pueden asignarse las variables de manera inmediata:

1

var arreglo = [2, 3, "Hola", variable, false];

Es posible acceder a la información dentro de un arreglo ocupando su índice, si utilizamos la definición anterior arreglo[0] tendrá el valor 2. Los índices van desde cero y llegan a n - 1, donde n es la cantidad de elementos del arreglo Veremos los arrays con más detalle en un próximo capítulo.

Objetos Los objetos tienen propiedades y métodos como en la vida real lo tendría un automóvil, un automóvil tiene como propiedades color, marca, modelo entre otros. Mientras que también tiene los métodos encender, apagar, avanzar, retroceder, etc. Para definir un objeto escribimos:

1

var obj = {};

Esto definirá un objeto vacío. Los objetos al igual que los array tienen su propia sección en esta guía por lo que profundizaremos más adelante.

Memoria dinámica Javascript es un lenguaje de memoria dinámica. A diferencia de otros tipos de lenguaje las variables en javascript pueden cambiar el tipo de dato que guardan, o sea el código a continuación es perfectamente válido.

1 2 3

var a = "hola"; a = 21; a = true;

Los pros y contras de esto son bastante discutidos, pero lo que si es cierto es que es una posible causal de errores y por lo mismo cuando programemos en javascript tenemos que ser extra cuidadosos. Para poder visualizar el tipo de dato asignados a una variable utilizaremos la instrucción: console.log(typeof(x)); Donde x es la variable en cuestión.

Preguntas Antes de seguir avanzando deberías poder contestar las siguientes preguntas. ¿Cómo podemos verificar que -3.9 sea del mismo tipo de dato que 3.9? ¿Cuál es la diferencia entre true y "true"? ¿Qué pasa con typeof(x) si x cambia de 1.0 a "hola", mantiene el tipo o lo cambia?

¿Puede un array guardar datos del mismo tipo?

Capítulo 4

Operadores Los operadores en javascript permiten como dice su nombre operar sobre los diversos tipos de datos ya sea directamente o a través de variables, los resultados de las operaciones los mostraremos en pantalla con console.log() o con alert() o los asignaremos a otra variable para futuras operaciones. Los operadores se dividen en: 1. Operadores aritméticos 2. Operadores de asignación 3. Operadores lógicos 4. Otros operadores

Operadores aritméticos Los operadores aritméticos en javascript sirven para poder realizar operaciones matemáticas ya sea sobre números u otro tipo de dato.

Operador Suma Para sumar datos ocuparemos el operador (+):

1 2 3 4

var var var var

suma = 1 + 2; a = 1; b = 2; c = a + b;

Una curiosidad del operador suma es que también sirve para strings, al sumar dos strings obtenemos un sólo string con el contenido de ambos. ejemplo:

1

console.log("hola " + "mundo ");

Operador resta Para sumar datos ocuparemos el operador (-):

1 2 3 4

var var var var

resta = 3; a = 3; b = 4; c = a -​ b;

Operador multiplicación Para multiplicar datos ocuparemos el operador (*), este funciona similar a los otros operadores de suma y resta:

1 2 3 4

var var var var

multiplica = 3 * 4; a = 3; b = 4; c = a * b;

Detalle importante respecto al operador multiplicación, al igual que en las matemáticas tradicionales tiene precedencia, eso quiere decir que ocurre primero que la suma. Ejemplo:

1

console.log(3 + 4 * 2);

Si la suma ocurriese primero, el resultado sería 7 * 4, o sea 12, sin embargo al igual que en las matemáticas de colegio, en una expresión sin paréntesis la multiplicación ocurre primero.

Operador División Para dividir datos ocuparemos el operador (/) Se comporta muy similar al operador de multiplicación, y tiene la

misma precedencia.

1 2 3 4 5

var divide = 10 / 2; var a = 10; var b = 2; var c = a / b; // c tendría el valor de 5

Un detalle importante del operador división es que a diferencia de otros lenguajes devuelve la división exacta, o sea:

1 2

console.log (3 / 2); // Mostraría 1.5

En muchos otros lenguajes la división entre dos números enteros tiene como resultado un número entero, pero en javascript no existe el tipo de dato entero, sólo existe el tipo de dato number y este se puede dividir sin problemas. Siendo un poco más técnico los numbers son puntos flotantes de 64 bits.

Operador módulo El operador módulo es muy útil para obtener el resto de las divisiones. Para obtener el módulo (%): var modulo = 10 % 2; Un ejemplo con variables:

1 2 3

var a = 10; var b = 2; var c = a % b;

Operador de asignación El más básico de todos los operadores de asignación ya lo hemos ocupado, es el operador = y permite asignar un valor a una variable.

Operador incremento Para incrementar el valor de una variable en 1 (++), ejemplo:

1 2

var a = 3; a++;

Operador decremento Para disminuir en 1 el valor de una variable (​​): nombreVariable​​;

1 2

var a = 3; a--​​;

Recordatorio Si no estas seguro de que el resultado de una operación sea el correcto puedes imprimir los tipos de datos con console.log()

Preguntas Antes de seguir debes ser capaz de contestar las siguientes preguntas. 1. ¿Qué obtienes al sumar 1 + "1"? 2. ¿Qué obtienes al sumar "1" + "1"? 3. ¿Qué obtienes al dividr 1 por 2? 4. ¿Cuál es el resultado de 1+2*3? 5. ¿Qué es la precedencia de operadores?

Operadores de Comparación Sirven para poder realizar comparaciones entre las variables que se estén comparando, como resultado devuelven un booleano que puede ser true o false.

Comparación de igualdad Igual a, se hace con (==) Ejemplo:

1 2 3 4 5 6

​3 == 4; // devuelve false 3 == 3; // devuelve true 3 == "3" // devuelve true

Comparación de tipo Esto lo podemos lograr con ocupando typeof()

1

typeof(3) == typeof("3");

Comparación de igualdad y tipo Exactamente igual, se hace con (===) Ejemplo:

1 2 3

3 === "3"; // devuelve false 3 === 3; // devuelve true

Operador Distinto Devuelve true cuando las expresiones a sus lados son diferentes. Ejemplo:

1 2 3 4

3 != 3; // devuelve false 3 != 4; // devuelve true

Operador distinto y distinto tipo Devuelve true cuando las expresiones a sus lados son diferentes, aunque esta diferencia sea sólo en el tipo. Por ejemplo si comparamos:

1 2 3 4

3 !== "3"; // devuelve true 3 !== 3; // devuelve false

Operador Mayor (>) 1 2 3 4

3 > 2; // devuelve true 3 > 4; // devuelve false

Operador menor (=) 1 2 3 4

3 >= 3; // devuelve true 3 >= 4; // devuelve false

Menor o igual ( falso falso y verdadero => falso falso y falso => falso

El operador or Simbolizado && permite obtener el resultado de la operación de la únion lógica.

Tabla de verdad del operador || 1 2 3 4

verdadero o verdadero => verdadero verdadero o falso => verdadero falso o verdadero => verdadero falso o falso => falso

El operador not (!) Invierte el valor, transforma verdadero en falso y falso en verdadero.

Tabla de verdad del operador ! 1 2

!verdadero => falso !falso => verdadero

Pregunta rápida 1 2 3

a = false; console.log(!a) // ¿Cuál es el valor mostrado en pantalla ?

Otros operadores Concatenación La concatenación permite unir 2 strings como si fuesen sólo uno. esto ya lo vimos previamente pero es bueno

reforzarlo

1 2 3

var a = "Hola "; var b = "mundo "; var c = a + b; // “Hola mundo”

La variable c del ejemplo anterior, si la imprimimos en la consola mostrará "Hola mundo", debido a que las variables a y b fueron concatenadas. Hay un detalle muy importante de la concatenación que es la causa de muchos errores, la suma de un entero con un string tiene como resultado un string, o sea.

1 2

console.log(1 + "1") // mostrará 11

La forma de lidiar con esto se le llama parsing, que es convertir un dato de un tipo en otro tipo (no es cambiar el valor, es cambiar el tipo). La función parseInt es capaz de convertir un string en un integer que represente el mismo valor, ejemplo de uso:

1 2 3 4

var a = parseInt("1"); var b = 1; console.log(a + b); // mostrará 2

Fallando en el parsing Cuidado Debemos tener mucho cuidado al hacer parseo, por ejemplo al convertir a número algo que no sea posible convertirse.

Al hacer comparaciones de este tipo obtendremos errores complejos de controlar.

En el caso anterior se entiende fácilmente lo que está mal, pero en un programa grande puede llegar a ser difícil encontrar estos problemas.

NaN

NaN es un valor que sirve para representar algo que no es un número, por si solo rara vez se usa, pero es posible obtenerlo de una operación, por ejemplo al hacer parseInt("hola") Para trabajar con este valor existe la función isNaN que nos devuelve true o false dependiendo de si el argumento es o no es un número isNaN

resultado

isNaN(123)

false

isNaN(-1.05)

false

isNaN(5-2)

false

isNaN(0)

false

isNaN(‘123’)

false

isNaN(“)

false

isNaN(true)

false

isNaN(‘2015/09/03’)

true

isNaN(‘Hello’)

true

isNaN(undefined)

true

isNaN(‘NaN’)

true

isNaN(NaN)

true

isNaN(0 / 0)

true

Preguntas Antes de seguir debes ser capaz de contestar las siguientes preguntas. 1. ¿Qué obtienes al sumar 1 + parseInt("1")? 2. ¿Qué obtienes al sumar 1 + parseInt("hola")? 3. ¿Cuál es el resultado al sumar 1 + parseInt("hola")?

Capítulo 5

Condiciones Las condiciones en javascript sirven para poder tomar decisiones en cuanto al código que se escribe, lo que hacen es ramificar el código, y la secuencia deja de leerse linealmente, y pasa a leerse dependiendo de la rama

if if es la condición más sencilla, veamos un ejemplo:

1 2 3 4

var edad = 14; if (edad > 18){ console.log("Eres mayor de edad"); }

En ese caso todo lo que está dentro de las llaves {} sólo se ejecuta si se cumple la condición. Lo que recibe la expresión if es un valor booleano, puede ser true o false, si es true se ejecuta, si es false no lo hace.

else En algunos casos necesitamos ejecutar un código sólo si la condición no se cumple, para eso la instrucción else viene al rescate.

1 2 3 4 5 6 7 8 9

var edad = 14; if (edad > 18) { console.log("Eres mayor de edad"); } else { console.log("Eres menor de edad"); } console.log("Este código se ejecuta independiente de si eres mayor de edad o menor");

else if vs doble if Existe un punto medio entre el if y else, se llama else if, esta condición se evalúa siempre y cuando el if anterior o el else if anterior devuelvan false. Para ilustrarlo esto veamos un ejemplo sencillo, queremos determinar si una persona es niño, adolescente, adulto.

1 2 3 4 5 6 7 8 9 10 11 12

var edad = 5; if (edad < 13) { console.log("es niño"); } if (edad < 18 ){ console.log("Es adolescente"); } else { console.log("Es adolescente"); }

En el código anterior si una persona tiene 12 años, entonces se mostrará en pantalla que es niño, pero además se mostrará que es adolecente, puesto que ambos if se evaluan, para evitar este tipo de situaciones existe el else if

1 2 3 4 5 6 7

if(edad < 13) { console.log("es } else if(edad < 18 console.log("Es } else{ console.log("Es }

niño"); ){ adolecente"); adolecente");

La instrucción else if sólo se evalúa si la condición anterior no se cumple, y el else sólo se evalúa si ninguna de las condiciones anteriores se cumple.

ifs anidados Es perfectamente posible tener un if dentro de un if, supongamos que queremos revisar si una persona es mayor de 18 y es zurdo eso lo podemos hacer de la siguiente forma:

1 2 3 4 5 6 7

var edad = 30; zurdo = true; if (edad > 18){ if (zurdo == true){ console.log("Es zurdo y mayor de edad"); } }

El problema de utilizar ifs anidados es que aumentan muchos las posibles rutas de código lo que hace el código difícil de revisar, este tipo de situaciones puede ser mejorado con un poco de lógica booleana.

Lógica booleana para romper ifs anidados Utilizando esa mismas tablas nosotros podemos remplazar los ifs anteriores ocupando:

1 2 3

if (edad > 18 && zurdo == true){ console.log("Es mayor de edad y zurdo"); }

En la lógica booleana debemos tener especial cuidado con el operador not, puesto que no (a y b) = no (a) o no (b). Ejercicios resueltos

El mayor de tres números Si se dan tres números, a, b, c y se pide determinar al mayor, ¿cómo lo podemos resolver? Si bien es posible utilizar ifs anidados para resolverlo, vamos a utilizar lo aprendido para resolverlo de forma inteligente.

1 2 3 4 5 6

if (a >= b && a >= c){ console.log("a es el mayor"); } else if (b >= c){ console.log("b es el mayor"); }

7 8 9

else { console.log("c es el mayor"); }

Se deja como tarea al lector resolver el mismo problema con ifs anidados, y un ejercicio no menos interesante es hacerlo con cuatro números. Además el código anterior no determina correctamente el número mayor en caso que algunos sean iguales, ese es otro ejercicio interesante que se deja de tarea.

Piedra papel o tijera En esta versión del famoso juego de niños, dado dos valores que pueden ser piedra, papel o tijera hay que determinar quien gana. Las reglas del juego son muy conocidas pero las vamos a explicar igual 1. Piedra le gana a tijera, pierde contra papel. 2. Tijera le gana a papel, pierde contra piedra 3. Papel le gana a piedra y pierde contra tijera. El secreto para resolver este problema es no complicarse innecesariamente, no necesitamos saber a quien le gana y contra quien pierde, para determinar al ganador, sólo tenemos que saber a que le gana a que y nuevamente, el secreto es mantenerse alejado de los ifs anidados.

Combinaciones posibles Entonces, dada dos variables, a y b que pueden contener los strings "piedra", "papel" o "tijera" tenemos 9 combinaciones posibles. 1. piedra vs piedra 2. piedra vs papel 3. piedra vs tijera 4. papel vs piedra 5. papel vs papel 6. papel vs tijera 7. tijera vs piedra

8. tijera vs papel 9. tijera vs tijera

Solución 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

if (a == "Piedra" && b == "Piedra"){ console.log("Empate"); } elsif (a == "Piedra" && b == "Papel"){ console.log("Gana Papel"); } elsif (a == "Piedra" && b == "Tijera"){ console.log("Gana Piedra"); } elsif (a == "Papel" && b == "Piedra"){ console.log("Gana Papel"); } elsif (a == "Papel" && b == "Papel"){ console.log("Empate"); } elsif (a == "Papel" && b == "Tijera"){ console.log("Gana Tijera"); } elsif (a == "Tijera" && b == "Piedra"){ console.log("Gana Piedra"); } elsif (a == "Tijera" && b == "Papel"){ console.log("Gana Tijera"); } elsif (a == "Tijera" && b == "Tijera"){ console.log("Empate");

Se deja de tarea realizar el mismo problema con ifs anidados, en este caso la solucón es más corta, pero requiere de un poco más de análisis.

Operador ternario El operador ternario es otra forma de escribir if pero con menos código, la lógica es la siguiente: expresión booleana ? expresion1 : expresion2

1 2 3

edad = 19; resultado = edad > 18 ? "es mayor de edad" : "no lo es"; // resultado muestra si

Capítulo 6

Ciclos Los ciclos, también conocidos como loops en inglés permiten ejecutar un bloque de código un determinado número de veces. Para realizar los loops podemos ocupar la instrucción for o la instrucción while.

For La sintaxis para el loop for es la siguiente:

1 2 3

for(var i = 0; i < 10; i++) { console.log("Esto se imprimirá 10 veces."); }

Un for se compone de tres partes: 1. El valor inicial: La sección var i = 0 es la primera condición, indica que el loop comenzará desde 0. La sección i < 10 es la segunda condición, indica que el bloque de código se debe ejecutar siempre que se cumpla esta condición. 2. La condición de mantención: El loop se mantiene mientras se cumpla esta condición, o sea en el ejemplo mientras que i < 10 3. La sección i++ indica que al terminar de ejecutar el bloque de código, debe ejecutarse esta instrucción, en este caso la instrucción es aumentar el valor en uno.

Sumatoria con For Supongamos que queremos sumar todos los valores de 0 a 99 con un for, eso lo podemos hacer con:

1

var suma = 0: for(var i = 0; i < 100; i++) {

2 3 4

suma += i; }

Sumando sólo los números pares Para hacerlo un poco más difícil digamos que en este caso queremos sumar los primeros 100 números, pero sólo si el número es par. Los números pares son todos aquellos divisibles por dos, para revisar esto ocuparemos el operador módulo que para obtener el resto de la división y compararla con cero, si no hay resto entonces el número es par, si hay resto entonces es impar.

1 2 3 4 5 6

var suma = 0: for(var i = 0; i < 100; i++) { if (i % 2 == 0){ suma += i ; } }

Versión inteligente En lugar de generar todos los números si son pares o no, podríamos generar exclusivamente números pares, cambiando la condición de incremento.

1 2 3 4 5

var suma = 0; for(var i = 0; i < 100; i = i + 2) { console.log(i); suma += i; }

El secreto para ser un buen programador es hacer las cosas de la forma más sencilla posible.

Ingresando elementos For no solo sirve para sumar, es posible pedirle al usuario que ingrese n elementos para mostrarlos

1 2 3 4 5

var n = 5; for(var i = 0; i < n; i++) { var ingreso = prompt("Ingrese un número"); }

Luego podemos utilizar la misma idea anterior para sumar los resultados (ya pronto podremos hacer cosas más interesantes que sumar)

1 2 3 4 5 6 7

var n = 5; suma = 0; for(var i = 0; i < n; i++) { var ingreso = prompt("Ingrese un número"); suma += ingreso; }

Al correr el código anterior si ingresamos los números 1,2,3,4,5 obtendremos como resultado "012345" ¿Cómo podemos hacer para arreglarlo?

For sin condición Es posible quitarle la condición de inicio, o la de incremento o la de cumplimiento a un for, para eso simplemente no la ingresamos pero debemos poner el ;

1

for (var i = 0; i < 100; ) { console.log(i += 1) }

Cuando omitimos algunas de las condiciones, podemos dejar sólo el ; en su lugar, pero debemos tener cuidado de que el ciclo no sea infinito.

While Otra forma similar para generar ciclos es con while, funciona de una forma muy similar y al igual que el for también se ejecutará un número determinado de veces siempre y cuando se cumpla con una condición. La sintaxis para el ciclo while es la siguiente:

1 2 3 4

var i = 0; while(i < 10) { console.log("Esto se imprimirá 10 veces."); }

La principal diferencia con el ciclo for que vimos anteriormente es que debe indicarse cuanto vale “i” antes del ciclo, además debe manejarse que se realizará con i dentro del mismo ciclo. La porción de código anterior se ejecutará 10 veces, ya que comenzará con i = 0 , y se aumentará su valor en 1, finalmente, cuando “i” sea igual a 10, el loop terminará.

Do - while Do while es similar a while, pero el ciclo siempre se realiza una vez antes de revisar la condición, la sintaxis básica es:

1 2

do { } while (condición)

Esto es muy útil para validar entradas, pro ejemplo supongamos que tenemos que hacer un programa donde el usuario tiene que ingresar dos números y luego debemos sumarlos:

1 2 3 4 5 6 7 8 9 10 11 12

var ingreso1; var ingreso2; do { ingreso1 = prompt("Ingrese el primer número"); } while (isNaN(ingreso1)); do { ingreso2 = prompt("Ingrese el segundo número"); } while (isNaN(ingreso1)); alert(parseInt(ingreso1) + parseInt(ingreso2));

Los ciclos anteriores se repetirán mientras el valor ingresado no sea un número.

Regla de transformación: Todo ciclo while puede ser transformado en un for y todo for en uno while, así como los ciclos do-while se pueden transformar a while y for y viceversa. Se deja como ejercicio al lector crear una versión del código de las sumatoria y de la revisión de números primos utilizando while en lugar de for.

Antes de seguir leyendo deberías poder contestar las siguientes preguntas 1. ¿Qué problemas podríamos tener si no validamos una entrada de datos? 2. ¿Qué precauciones tenemos que tomar antes de convertir un do-while a un while 3. ¿Qué pasa si dentro del for no ingresamos uno de las condiciones?, ejemplo (for var i = 0; ; i += 1)

Break: Terminando el ciclo antes de tiempo. Los loops “for” y “while” se pueden terminar antes en cualquier momento con la instrucción “break”, esto terminará la ejecución del loop y continuará con el código siguiente.

1 2 3 4 5 6 7

var i = 0; while (i < 10){ if (i === 5){ break; } console.log(“La variable i vale: ” + i); i++; }

En el ejemplo anterior, el loop while terminará cuando i sea igual a 5, ya que se ejecutará la línea donde se encuentra “break”.

Continue: Pasando a la siguiente vuelta En algunos casos si tenemos un ciclo complejo, la opción continue nos puede ayudar, por ejemplo si tenemos un calculo que es muy complicado pero para cierto número lo podemos omitir entonces ahí es cuando continue nos ayuda.

1 2 3 4 5 6 7 8

var j = 0; for (var i = 0; i < 100; i ++){ if (i === 5){ continue; } j++; console.log(i + "," + j) }

Cuando i toma el valor de 5 las instrucciones de j++ y console.log no serán ejecutadas, a partir de la siguiente vuelta j ya no estará en sincronía con i. Veamos un ejercicio un poco más complejo.

Revisando si un número es primo Un clásico ejercicio de programación universitaria es crear un pequeño algoritmo que determine si un número es primo o no. Los números primos son todos aquellos que son únicamente divisibles por 1 y por si mismos. Dado que los primos son aquellos que no son divisibles entonces lo que vamos a hacer es contar divisiones, si las hay entonces el número no es primo. Importante, partiremos 2 ya que el 1 siempre divide y no nos interesa contarlo y revisaremos hasta n - 1.

1 2 3 4 5 6 7 8 9 10 11 12 13 14

var numero_a_revisar = 11; var cuenta_divisores = 0; for (var i = 2; i < numero_a_revisar; i++) { // revisamos si el número es divisible if (numero_a_revisar % i == 0){ cuenta_divisores++; } } if (cuenta_divisores > 0){ console.log("el número no es primo"); } else{ console.log("el número es primo"); }

Ciclos anidados Así como los ifs se pueden anidar, los ciclos también se pueden anidar, esto tiene bastante utilidades, la principal de ellas es manejos de matrices. Es muy cierto que hasta este momento el principal uso que le hemos dado a los ciclos es para cálculos matemáticos, pero no es el único. Eventualmente tendremos arrays con información que sacaremos de bases de datos y en ese caso tendremos que iterar con for o while para mostrar todos sus valores, hasta entonces los casos prácticos que hagamos serán con números y dibujos. y hablando de dibujos vamos por nuestro primero dibujo.

Dibujando un bloque de * En este ejercicio dibujaremos un cuadrado de tamaño 5 con *, o sea serán 5 * de lado y 5 de alto. La solución más evidente es:

1 2 3 4 5

console.log("******"); console.log("******"); console.log("******"); console.log("******"); console.log("******");

Pero ¿Cómo podemos hacerlo para dejarlo parametrizado?, o sea que el resultado dependa del input del usuario el tamaño de nuestro cuadrado.

Solución paramétrica Supongamos que no nos interesa el tamaño del lado, vamos por un momento a preocuparnos únicamente de la altura. Entonces podríamos parametrizas la solución de la siguiente forma:

1 2 3 4

var size = 5; for (i = 0; i < size; i ++){ console.log("******"); }

Ahora lo que tenemos que resolver sabemos que está dentro del for, para eso vamos a imprimir los * de dentro del for de a uno.

1 2 3 4 5 6

var size = 5; for (i = 0; i < size; i ++){ for (j = 0; j < size; j++){ console.log("*"); } }

El problema de la solución anterior es que nos arroja una sola línea de *, 25 veces debido a que console.log también imprime el salto de línea, pero eso lo podemos solucionar concatenando los strings e imprimiéndolos una sola vez.

1 2 3 4 5 6 7 8

var size = 5; for (i = 0; i < size; i ++){ asteriscos = ""; for (j = 0; j < size; j++){ asteriscos += "*"; } console.log(asteriscos); }

En chrome la solución no se ve muy elegante porque la agrupa, pero si indicamos el piso de la torre se verá mejor.

1 2 3 4 5 6 7 8 9 10 11 12 13

var size = 5; for (i = 0; i < size; i ++){ asteriscos = ""; for (j = 0; j < size; j++){ asteriscos += "*"; } console.log(i + " - " + asteriscos); } /* 0 - ***** 1 - ***** 2 - *****

14 15 16

3 - ***** 4 - ***** */

Ups, ahora nuestra torre está invertida, el piso 0 está arriba, podemos invertir el indice restándoselo al tamaño. Este tipo de soluciones cuesta verlos al principio pero después de mucha práctica ocurren de forma instantánea.

1 2 3 4 5 6 7 8

var size = 5; for (i = 0; i < size; i ++){ asteriscos = ""; for (j = 0; j < size; j++){ asteriscos += "*"; } console.log(size - i + " - " + asteriscos); }

El problema de la media pirámide. Vamos a complicar un poco más el caso anterior, ahora en lugar de dibujar un cuadrado vamos a dibujar una pirámide. La pirámide que vamos a dibujar tiene la siguiente forma:

1 2 3 4 5

* ** *** **** *****

Antes de ponernos a escribir código tenemos que pensar que caracteriza a una pirámide, y es que la base se va achicando a medida de que crece y se achica en la misma proporción de lo que crece. Resolver problemas tiene mucho que ver con encontrar patrones, en este caso el patrón es que la cantidad de pisos determina la cantidad de asteriscos

1 2 3

* 1 ** 2 *** 3

4

***** 4

pero que pasa si representamos la pirámide de otra forma, piso, cantidad de *, tendríamos:

1 2 3 4

* 1,1 ** 2,2 *** 3,3 ***** 4,4

O sea dentro de los for un número está creciendo siempre de uno en uno (el del piso) y el de los lados llega hasta el piso respectivo, en lugar del tamaño del cuadrado. Para implementar ese código lo único que tenemos que hacer es limitar el j para que en lugar de llegar hasta size, llegue hasta i.

1 2 3 4 5 6 7 8

var size = 5; for (i = 0; i < size; i ++){ asteriscos = ""; for (j = 0; j < i; j++){ asteriscos += "*"; } console.log(size - i + " - " + asteriscos); }

Ejercicios para practicar ciclos anidados Dibujar una letra I de tamaño n Ejemplo si tamaño = 1

1 2 3

*** * ***

si la letra de es de tamaño 2

1 2 3 4

***** * * *****

Y si es de tamaño 3

1 2 3 4 5

******* * * * *******

Capítulo 7

Funciones Introducción a funciones En el capítulo anterior aprendimos a crear un cuadrado de tamaño x, o una pirámide de tamaños x, imaginemos ahora que este proceso lo tuviésemos que hacer muchas veces en nuestro sitio, tendría poco sentido tener que escribir el código cada vez, ahora imaginemos que descubrimos un error o nos piden cambiar todos los cuadrados por pirámides en nuestra tendríamos que cambiar nuestro código en muchas partes distintas. En javascript al igual que en muchos otros lenguajes existen las funciones, estas nos permiten nombrar una serie de pasos y ejecutarlos con un simple llamado, de esta forma evitamos repetir toda ls serie de pasos cada vez que se quiera ejecutar y nos permite actualizar y/o reparar la función en un solo punto. Las funciones son la herramienta más básica para estructurar programas largos, reducir la repetición, asociar nombres con subprogramas y poder aislar estos subprogramas unos de otros.

Nuestra primera función El secreto para entender funciones es que en una parte de nuestro código se define, y en otras es llamada. La definición consta con una secuencia de pasos que se ejecutan con un nombre. Por ejemplo, el siguiente código define la función mostrar códigos secretos.

1 2 3 4 5

var mostrarCodigos = function(){ console.log("123xxf"); console.log("1842fy"); console.log("zyPP9x"); };

Luego podemos escribir mostrarCodigos y ver en la consola todos los códigos cada vez que queramos.

Composición una función

Una función tiene un nombre y es creada por una expresión que empieza con la palabra reservada function. Las funciones reciben una lista de parámetros entre medio de los (), en nuestro caso no recibimos ninguna función pero hablaremos de eso un poco más adelante. En javascript el cuerpo de las funciones siempre deben ser envueltos en llaves {} , como en el ejemplo de los códigos secretos. Finalmente las funciones pueden tener un retorno de algún valor particular, pero no es obligatorio.

Nombrando funciones El nombre de una función debe ser compuesto de una sóla palabra, como por ejemplo alCuadrado, en lo posible se debe ocupar el nombre menos errático y misterioso, el nombre de la función puede contener números pero no puede empezar con uno. A esta nomenclatura de juntar palabras y la primer letra de cada palabra (después de la primera) empieza con mayúsculas se le denomina lower camel case. Esto es sólo una convención y puede ser violada, pero como práctica no se recomienda. Ejemplos de nombres:

1 2 3 4 5 6 7 8

incrementar(); // Correcto emparejar(); // Correcto suavizar(); // Correcto x2(); // Correcto pero no se nos ocurre para que sirve 2x(); // Incorrecto no puede empezar con un número X2(); // está permitido, pero no debería empezar con mayúsculas calcularAño(); // Es válido, los nombres pueden contener tildes y la letra ñ.

Pasando parámetros Las funciones pueden recibir parámetros, por ejemplo imaginemos que queremos ocupar la misma función para construir una pirámide de tamaño 5, o una de tamaño 10, no tendría sentido escribir el código para cada tamaño, lo que se hace es parametrizar la función.

1

var drawPiramid = function(size)

2 3 4 5 6 7 8 9 10

{ for (i = 0; i < size; i ++){ asteriscos = ""; for (j = 0; j < i; j++){ asteriscos += "*"; } console.log(size - i + " - " + asteriscos); } }

De esta forma cuando llamemos a dibujar pirámide lo podemos hacer del tamaño que queramos. ejemplo:

1 2

drawPiramid(10); drawPiramid(20);

Una función no está limitada a recibir un único parámetro, perfectamente podría recibir dos o tres, incluso es posible que sea un número indefinido, aunque este número nunca puede ser infinito, eso lo veremos más adelante. Cuando se pasa más de un parámetro el orden de estos determina cual es cual. Ejemplo:

1 2

var calcularIMC = function(peso, estatura){ }

Si se llama a la función como calcularIMC(1.80, 80) el sistema confundirá peso con estatura y los resultados arrojados probablemente estarán malos. Por lo mismo debemos ser cuidadosos de no confundir el orden de los parámetros. Moraleja: El orden de los parámetros importa. Tarea: Se deja como tarea crear una función que dibuje un rectángulo de lados x, e y.

Retorno de funciones

Es importante entender que las funciones pueden devolver valores o simplemente no devolver nada, cuando una función no devuelve nada javascript lo interpreta como undefined. Por ejemplo nuestra función drawPiramid() no devolvía valores y por lo mismo cuando uno la llama aparece un texto en la consola después del dibujo que dice undefined. Para devolver un valor se utiliza la instrucción return, cuando se llama la función el valor es devuelto y es nuestro deber capturarlo o si no se pierde. Ejemplo:

1 2 3

var calcularIMC = function(peso, estatura){ return peso / (estatura * estatura); }

Luego podemos mostrar el valor llamando a la función con console.log(calcularIMC(100, 2.00)) La función termina después del return, pero eso no quiere decir que no pueda tener más de uno, siempre y cuando sea en un camino distinto del código.

1 2 3 4 5 6 7 8 9 10

var interpretarIMC = function(peso, estatura){ var imc = calcularIMC(peso, estatura); if (imc > 24){ return "sobrepeso"; } else if (imc > 19) { return "ok"; } else { return "bajo peso"; } }

y luego podemos utilizarla de la siguiente forma:

1 2 3 4 5 6

interpretarIMC(80, 1.79); // "sobrepeso" interpretarIMC(60, 1.79); // "bajo peso" interpretarIMC(70, 1.79); // "ok"

En la definición de la función también pudimos observar que estamos llamando a otra función, eso es perfectamente posible, también habría sido posible crear dos funciones distintas, de la siguiente forma:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

var calcularIMC = function(peso, estatura){ return peso / (estatura * estatura); } var interpretarIMC = function(peso, estatura){ var imc = calcularIMC(peso, estatura); if (imc > 24){ return "sobrepeso"; } else if (imc > 19) { return "ok"; } else { return "bajo peso"; } }

Pero en este caso para interpretar el IMC tendríamos que ocupar ambas funciones por separado, de esta forma:

1 2

imc = calcularIMC(90, 2.00); console.log(interpretarIMC(imc));

Cual de las dos formas a utilizar se deja a criterio del lector pero que existe una rama de la informática especializada en estudiar como acoplar y desacoplar códigos y se llama diseño de patrones, el cuál es un tema que abordaremos más adelante en este libro.

Capturando el valor de retorno Este es un tema que ya mencionamos pero es tan importante que lo repetiremos, cuando una función retorna un valor debemos capturarlo, si no lo perdemos, eso es lo que estamos haciendo en al función interpretarIMC cuando escribimos var imc = calcularIMC(peso, estatura) estamos almacenando el retorno en la variable imc. Cuando se construye una función principalmente hay dos cosas claves, una es que recibe y la otra es que devuelve. Se deja como tarea para el lector crear la función que revise si un número es primo o no.

Otra forma de definir funciones. Existe una segunda forma de definir una función que no hemos mencionado todavía, consiste en utilizar la palabra reservada function

1 2 3

function formaNueva(){ return 'otra forma de declarar funciones'; }

La diferencia entra ambas es sutil y muy técnica, pero ambas sirven para lo mismo, en ambos casos se crea una variable en que en el segundo caso es implícito.

El scope de las variables dentro de una función Variables locales Toda variable definida dentro de una función es una variable local y no puede ser accedidas afuera de la función.

1 2 3 4 5

var miFuncion = function(){ var y = 10; }; console.log(y)

En el ejemplo anterior obtendremos un error ya que la variable y no existe fuera de la función llamada miFuncion() incluso aunque llamemos a la función veremos que todavía no existe y

1 2

miFuncion() console.log(y)

Este comportamiento es el esperado y es bueno porque evita que rompamos una función sin querer.

Variables globales Las variables definidas afuera de una función son llamadas globales, pueden ser accedidas y ser modificadas dentro de una función. En el siguiente código de puede ver el ejemplo de ambos conceptos.

1 2 3 4 5 6 7

var x = 1; var otraFuncion = function(){ x = x + 1; console.log(x) } console.log(x)

En este ejemplo podemos ver que x tiene el valor de 1, y claro no se ha incrementado porque todavía no llamamos a la función, pero ese no es el único detalle, a diferencia del caso anterior ahora vemos que x si existe. Ahora llamemos a la función para ver que pasa:

1 2 3

otraFuncion() otraFuncion() console.log(x)

Cada vez que llamamos a otra función estamos incrementando el valor de x para todas partes, este es un comportamiento peligroso, porque en un código grande no sabremos muy bien que cosa está modificando a que otra. Es un error de diseño que debemos evitar.

Muy importante Nunca utilizar variables globales, tarde o temprano se levantarán de sus tumbas y vendrán a penarnos.

Funciones de primera clase Javascript es considerado un lenguaje funcional, una de sus principales razones es que trata las funciones como objetos de primera clase, en español eso quiere decir las funciones pueden ser parámetros de funciones y las funciones pueden retornar funciones, tal como si fuera cualquier otro tipo de variable.

1 2 3 4 5 6 7 8 9 10 11

var multiplicaPorTres = function(x){ return 3*x; }; var aplicaDosVeces = function(x, miFuncion){ return miFuncion(miFuncion(x)); }; var resultado = aplicaDosVeces(6, multiplicaPorTres); console.log(resultado); // -> 54

Funciones anónimas Llegó el momento de confesar una verdad, hasta el momento todas las funciones que hemos estado ocupando son anónimas, lo que sucede es que se las asignamos a una variables, pero no siempre tiene que ser así. Para entender bien esta situación ilustremos dos casos, en el primero vamos a crear una función anónima y asignarla una variable y luego utilizarla dentro de una función, y, en un segundo caso, vamos a pasar directamente la función.

Pasando una variable que contiene una función Miremos por ejemplo la función setInterval(), la función setInterval recibe como parámetro otra función y un tiempo y ejecuta esa función cada cierto tiempo, ejemplo:

1 2 3 4 5

var mostrarAlerta = function(){ alert("hola"); } setInterval(mostrarAlerta, 3000);

Un lector bien atento notará que la función mostrarAlerta es pasada sin utilizar los paréntesis como usualmente se usa. La razón se debe a que si los utilizáramos así setInterval(mostrarAlerta(), 3000); estaríamos ejecutando la función y pasando el resultado (undefined) en lugar de pasarla como una variable.

Pasando directamente una función. Ahora veamos el caso contrario pasando directamente la función.

1 2 3

setInterval(function(){ alert("hola") }, 3000);

Este tipo de sintaxis es muy utilizada en javascript y la ocuparemos mucho especialmente cuando trabajemos con arreglos u otras librerías como underscore, lowdash o jQuery, así que volveremos a hablar de este tema pronto en el libro.

Capítulo 8

Arrays Los arreglos son un tipo de dato que permite contener múltiples datos agrupados en una sola variable, podemos acceder a estos datos de dos formas: 1. Directamente a través del índice. 2. Secuencialmente a través de un for o while.

Formas de crear un arreglo Hay dos formas de crear un arreglo, una recomendada y otra no, pero ambas funcionan. La forma buena y sencilla es var arreglo = [1,2,3,4] , La forma no tan buena es var arreglo = new Array(1,2,3,4) La razón por la que no se recomienda ocupar new para el array es porque cuando sólo se pasa un parámetro se comporta de una forma peculiar.

1 2

array = new Array(5) // [undefined × 5]

Con un sólo parámetro crea n elementos indefinidos. Moraleja: Ocupar siempre la primera forma para evitar errores. Para crear un arreglo vacío se puede hacer con var arreglo = []

El índice En javascript el índice de un array empieza desde 0, y termina en n - 1, o sea si hay 5 elementos, para acceder al primero sería arreglo[0] y para acceder al último sería arreglo[4]

1 2 3 4 5 6 7 8 9 10 11

var colores = ['rojo', 'azul', 'verde', 'amarillo']; console.log(colores[0]); // -> 'rojo' console.log(colores[2]); // -> 'verde' colores[4] = 'blanco'; console.log(colores); // -> ['rojo', 'azul', 'verde', 'amarillo','blanco']

Acceder a un índice más allá de los límites devolverá un elemento undefined.

Contenido dinámico Los arreglos en javascript pueden tener cualquier tipo de objetos, por ejemplo puedo tener en el mismo arreglo una variable string, un número y una función.

1 2 3 4 5 6 7

var miFunción = function(){ return true; }; var miNumero = 27; var miArreglo = ['Hola', miNumero, 15.52, miFuncion];

Largo del arreglo Los arreglos además tiene la propiedad length que nos permite conocer la cantidad de elementos que contiene

1 2 3

var colores = ['rojo', 'azul', 'verde', 'amarillo']; console.log(colores.length); // -> 4

Iteración

Se conoce como iteración de un arreglo al hecho de recorrerlo secuencialmente de principio a fin. Esto lo podemos hacer con los ciclos for y while que vimos previamente: Ejemplo básico de iteración:

1 2 3 4 5 6 7

for(var index = 0; index < colores.length; index++) { console.log(colores[index]); } // -> 'rojo' // -> 'azul' // -> 'verde' // -> 'amarillo'

Como queremos que nuestros códigos funciones para cualquier arreglo no debemos fijar arbitrariamente los límites del arreglo dentro del for y debemos ocupar la propiedad length. A el proceso de fijar límites y valores arbitrariamente dentro de los array se le conoce en la industria como hardcoding y es una práctica muy mal vista.

Antes de seguir leyendo deberías poder contestar las siguientes preguntas 1. ¿Para qué sirven los arrays? 2. ¿Qué hace new Array(10)? 3. ¿Puede el mismo array tener Strings y Numbers? 4. Crea un método que permite mostrar todos los tipos de datos que hay dentro de un arreglo que recibe como parámetro. 5. ¿Que obtendríamos si nos referimos al índice -1 de un arreglo?

Métodos implementados en todos los navegadores Los arreglos también tienen métodos, pero no todos están implementados en todos los navegadores, es por esto que hay que tener mucho cuidado al utilizarlos. A continuación veremos seis métodos soportados por todos los navegadores.

1. Push 2. Pop 3. Shift 4. Unshift 5. Concat 6. Slice Nota al margen: los métodos son muy similares a las funciones pero le pertenecen a un objeto, por ahora la principal diferencia que cabe mencionar es que para utilizar el método mencionaremos a la variable.funcion() en lugar de función() Veremos más de esto en el capítulo de objetos.

1. Método de array push(elemento) Agrega un elemento al final del arreglo.

1 2 3 4

var colores = ['rojo', 'azul', 'verde', 'amarillo']; colores.push('blanco'); console.log(colores); // -> ['rojo', 'azul', 'verde', 'amarillo','blanco']

No existe ningún problema en que un array tenga elementos repetidos, por, sería perfectamente valido agregar un elemento que ya está en la lista:

1 2

colores.push('rojo') console.log("colores")

2 Método de array pop() EL método pop realiza dos cosas simultáneamente, nos permite obtener el último elemento de un arreglo y además lo elimina del arreglo original.

1

var colores = ['rojo', 'azul', 'verde', 'amarillo'];

2 3 4 5 6

var ultimo = colores.pop(); console.log(ultimo); // -> 'amarillo' console.log(colores); // -> ['rojo', 'azul', 'verde']

No es necesario capturar el valor con lo variable último, si sólo queremos eliminar el valor del arreglo basta con colores.pop()

Método de array shift() Obtiene el primer elemento de un arreglo y lo elimina del arreglo original.

1 2 3 4 5 6

var colores = ['rojo', 'azul', 'verde', 'amarillo']; var primero = colores.shift(); console.log(primero); // -> 'rojo' console.log(colores); // -> ['azul', 'verde', 'amarillo']

Método de array unshift(elemento) Agrega un elemento al principio del arreglo.

1 2 3 4

var colores = ['rojo', 'azul', 'verde', 'amarillo']; colores.push('blanco'); console.log(colores); // -> ['blanco','rojo', 'azul', 'verde', 'amarillo']

Método de array concat(otroArreglo) Devuelve un nuevo arreglo que une el arreglo inicial con otro arreglo (o más de uno), pero no modifica el arreglo inicial.

1 2 3 4 5 6 7 8 9 10 11 12 13

var colores = ['rojo', 'azul']; var numeros = [1,2,3] var dias = ['lunes','martes']; var nuevoArreglo = colores.concat(numeros); console.log(nuevoArreglo); // -> ['rojo', 'azul', 'verde', 'amarillo','blanco'] console.log(colores); // -> ['rojo', 'azul'] var nuevoArreglo2 = colores.concat(numeros,dias); console.log(nuevoArreglo2); // -> ['rojo', 'azul', 'verde', 'amarillo','blanco','lunes','martes']

Slice Slice permite seleccionar algunos elementos de un arreglo.

1

array.slice(start,end)

donde start y end son índices, si no se específica el final entonces se copiará del principio señalado hasta el final, ejemplo.

1 2

array = ["a", "b", "c", "d","e", "f","g", "h"] array.slice(3) // ["d", "e", "f", "g", "h"]

Splice Splice permite añadir y remover elementos a un array, el método devuelve los items removidos. A pesar de ser un método que permite hacer múltiples cosas su principal uso es para remover elementos de un array.

1 2 3

var paises = ["Egipto", "Ghana", "Kenia", "Liberia", "Malí"] console.log(paises.splice(0, 1))

4 5 6

// Egipto console.log(paises) // ["Ghana", "Kenia", "Liberia", "Malí"]

Además es posible agregar elementos ocupando splice

1 2 3 4

console.log(paises.splice(0, 1, "Nigeria", "Ruanda")) // ["Ghana"] console.log(paises) ["Nigeria", "Ruanda", "Kenia", "Liberia", "Malí"]

Ejercicio con push & pop Crear un método que devuelva todos los elementos de un arreglo pero en orden inverso.

1 2 3 4 5 6 7

var invertirArreglo = function(arreglo_original){ var arreglo_invertido = []; for (var i = 0; i 'Hola Pedro' // -> 'Hola Juan' // -> 'Hola Diego'

El ejemplo anterior hace la funcionalidad esperada, sin embargo, tiene algunos problemas. Veremos cuales son estos con un ejemplo, ahora necesito saludar a “primos” y a “mascotas”.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

var amigos = ['Pedro', 'Juan', 'Diego']; var primos = ['Rodrigo','Jaime','Francisco']; var mascotas = ['Bobby','Campeón','Doggy', 'Pinky']; for(var index = 0; index < amigos.length; index++) { console.log('Hola '+ amigos[index]); } // -> 'Hola Pedro' // -> 'Hola Juan' // -> 'Hola Diego' for(var index = 0; index < primos.length; index++) { console.log('Hola '+ primos[index]); } // -> 'Hola Rodrigo' // -> 'Hola Jaime' // -> 'Hola Francisco' for(var index = 0; index < mascotas.length; index++) { console.log('Hola '+ primos[index]); } // -> 'Hola Rodrigo' // -> 'Hola Jaime' // -> 'Hola Francisco' // -> 'Hola undefined' // ¡Error!

Empecé a copiar y pegar código, pero no fui lo suficientemente cuidadoso! En el último “for” quería saludar a las mascotas pero se me olvidó reemplazar primos por mascotas, y además como mascotas tiene más elementos que primos apareció un error en la consola. Veamos cómo queda esto implementado con forEach.

1

var amigos = ['Pedro', 'Juan', 'Diego'];

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

var primos = ['Rodrigo','Jaime','Francisco']; var mascotas = ['Bobby','Campeón','Doggy', 'Pinky']; amigos.forEach(function(nombre){ console.log('Hola ' + nombre); }; // -> 'Hola Pedro' // -> 'Hola Juan' // -> 'Hola Diego' primos.forEach(function(nombre){ console.log('Hola ' + nombre); }; // -> 'Hola Rodrigo' // -> 'Hola Jaime' // -> 'Hola Francisco' mascotas.forEach(function(nombre){ console.log('Hola ' + nombre); }; // -> 'Hola Bobby' // -> 'Hola Campeón' // -> 'Hola Doggy' // -> 'Hola Pinky'

Como pueden ver, al repetir el código ya no se necesito preocupase por estar recorriendo el array correcto, forEach se encarga de hacer ese trabajo por nosotros. Son menos variables y por lo tanto menos preocupaciones para el desarrollador. Pero a ningún desarrollador le gusta repetir código y si quiero cambiar la forma de saludar, necesito cambiar el código en varios lugares. Eso significa tener más preocupaciones y mayores probabilidades de equivocarse. Esto lo puedo solucionar de la siguiente manera, creando el método saludar.

1 2 3 4 5 6 7 8 9 10

var saludar = function(nombre){ console.log('Hola ' + nombre); }; var amigos = ['Pedro', 'Juan', 'Diego']; var primos = ['Rodrigo','Jaime','Francisco']; var mascotas = ['Bobby','Campeón','Doggy', 'Pinky']; amigos.forEach(saludar); // -> 'Hola Pedro'

11 12 13 14 15 16 17 18 19 20 21 22 23

// -> 'Hola Juan' // -> 'Hola Diego' primos.forEach(saludar); // -> 'Hola Rodrigo' // -> 'Hola Jaime' // -> 'Hola Francisco' mascotas.forEach(saludar); // -> 'Hola Bobby' // -> 'Hola Campeón' // -> 'Hola Doggy' // -> 'Hola Pinky'

El código amigos.forEach(saludar), se puede leer de la siguiente manera: “para cada elemento del arreglo amigos aplicar el método saludar”. Muchos desarrolladores prefieren esta manera en vez de “for” ya que, entre otras razones, es mucho más explícito a lo que se quiere llegar a realizar. Por último, como se dijo anteriormente, el método forEach no está en todos los navegadores, y la implementación con Underscore quedaría de la siguiente manera:

1 2 3 4 5 6 7 8 9 10 11

// Original amigos.forEach(saludar); // -> 'Hola Pedro' // -> 'Hola Juan' // -> 'Hola Diego' // Underscore o Lodash _.forEach(amigos,saludar); // -> 'Hola Pedro' // -> 'Hola Juan' // -> 'Hola Diego'

map(función) Imaginemos que ahora en vez de saludar en consola a cada elemento del arreglo amigos, queremos guardar el saludo para cada uno de los elementos en un arreglo nuevo. Con los métodos forEach y push quedaría implementado de la siguiente manera:

1

var amigos = ['Pedro', 'Juan', 'Diego'];

2 3 4 5 6

var saludosAmigos =[]; amigos.forEach(function(nombre){ saludosAmigos.push('Hola ' + nombre); });

Esto funciona correctamente, pero si quiero replicar la funcionalidad con mascotas o primos, necesito replicar todo el código como se ve en el siguiente ejemplo.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

var amigos = ['Pedro', 'Juan', 'Diego']; var primos = ['Rodrigo','Jaime','Francisco']; var mascotas = ['Bobby','Campeón','Doggy', 'Pinky']; var saludosAmigos =[]; var saludosPrimos = []; var SaludosMascotas = []; amigos.forEach(function(nombre){ saludosAmigos.push('Hola ' + nombre); }); primos.forEach(function(nombre){ saludosPrimos.push('Hola ' + nombre); }); mascotas.forEach(function(nombre){ saludosMascotas.push('Hola ' + nombre); });

Para estos casos, cuando necesito crear un nuevo arreglo en base a uno existente, existe un método creado especialmente para ello. Se llama “map” y está implementado en la mayoría de los lenguajes modernos. Este método toma como base un array inicial, a cada uno de los elementos le aplica una función y guarda el resultado en un arreglo nuevo. Es importante entender que map no modifica el array inicial, lo que hace es crear uno nuevo. Veamos un ejemplo:

1 2 3 4 5 6

var amigos = ['Pedro', 'Juan', 'Diego']; var saludosAmigos = amigos.map(function(nombre) { return 'Hola ' + nombre; }); console.log(amigos)

7 8 9 10

// -> ['Pedro', 'Juan', 'Diego'] console.log(saludosAmigos); // -> ['Hola Pedro', 'Hola Juan', 'Hola Diego']

Ahora crearemos la función crearSaludo y la aplicaremos al resto de los arrays.

1 2 3 4 5 6 7 8 9 10 11

var amigos = ['Pedro', 'Juan', 'Diego']; var primos = ['Rodrigo','Jaime','Francisco']; var mascotas = ['Bobby','Campeón','Doggy', 'Pinky']; var crearSaludo = function(nombre){ return 'Hola ' + nombre; }; var saludosAmigos = amigos.map(crearSaludo); var saludosPrimos = primos.map(crearSaludo); var SaludosMascotas = mascotas.map(crearSaludo);

De esta manera queda implementada la funcionalidad esperada de una forma muy concisa, que fue crear un nuevo array a partir de otro modificando cada elemento de este. Para finalizar mostraremos cómo se implementa map con Underscore.

1 2 3 4 5

// Original var saludosAmigos = amigos.map(crearSaludo); // Underscore o Lodash var saludosAmigos = _.map(amigos,crearSaludo);

filter(función) Cuando se trabaja con arrays, muchas veces es necesario filtrar los valores, para eso existe el método filter. Filter devuelve un nuevo arreglo con los elementos filtrados, y para saber que filtrar necesita una función que retorna “true” si queremos mantener ese elemento en particular. Esto se puede saber en el siguiente ejemplo en vamos a filtrar los números menores a 10.

1 2

var numeros = [1, 5, 3, 20 , 15, 6]; var numerosMenoresA10 = numeros.filter(function(numero){

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

if(numero < 10){ return true; } }); console.log(numeros); // -> [1, 5, 3, 20 , 15, 6] console.log(numerosMenoresA10); // -> [1, 5, 3, 6] // Underscore o Lodash var numerosMenoresA10 = _.filter(numeros,function(numero){ if(numero < 10){ return true; } }); reduce(función [, valorInicial])

Los métodos “map” y “filter” devuelven arrays, sin embargo, a veces es necesario convertir un array en un solo valor, por ejemplo sumar todos los elementos de un array. Para eso existe el método reduce. La función en este caso tiene dos parámetros, valorAnterior y valorActual. Se puede pensar que el valorAnterior es el valor acumulado y valorActual es el valor actual del elemento. Veremos un ejemplo sumando todos los elementos de un array.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

var numeros = [1, 5, 3, 20 , 15, 6]; var sumTotal = numeros.reduce(function(valorAnterior,valorActual return valorAnterior+valorActual; }); console.log(sumTotal); // -> 50 Ahora vamos a multiplicar todos los valores. var multElementos = function(anterior,actual){ return anterior*actual; }; var multTotal = numeros.reduce(multElementos); console.log(multTotal); // -> 27000

Este tiene de manera opcional el valor inicial, en este caso Javascript asumió que el valor inicial de la suma es 0 y el valor inicial de la multiplicación es 1. Para evitar errores es aconsejable definir de manera implícita el valor inicial, como lo veremos a continuación.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

var sumTotal0 = numeros.reduce(function(a,b){return a+b;},0); var sumTotal1 = numeros.reduce(function(a,b){return a+b;},1); console.log(sumTotal, sumTotal0, sumTotal1); // -> 50 50 51 var multTotal0 = numeros.reduce(multElementos,0); var multTotal1 = numeros.reduce(multElementos,1); console.log(multTotal, multTotal0, multTotal1); // -> 27000 0 27000 Por último en Underscore se escribe de la siguiente manera. var multTotal = _.reduce(numeros,multElementos,1);

Combinando Filter, Map y Reduce Con estos 3 métodos se pueden hacer todas las transformaciones de un array y con Javascript se pueden combinar de alguna manera muy simple. Por ejemplo voy a filtrar los números menores a 10, multiplicarlos por 2 y luego sumarlos.

1 2 3 4 5 6 7 8 9 10 11 12 13 14

var numeros = [1, 5, 3, 20 , 15, 6]; var menor10 = function(x) { if(x 30 //Con Underscore o Lodash var resultado = _.filter(numeros,menor10) .map(mult2) .reduce(sumar,0);

Estos métodos tiene mayor relevancia al tener arrays de objetos, que serán visto más adelante. Por último, es altamente recomendable utilizar las librerías Underscore o Lodash para evitar problemas de compatibilidad. Ambas librerías además tienen más métodos disponibles en su documentación. http://underscorejs.org/ https://lodash.com/

Funciones Avanzadas Funciones autoejecutables El término en inglés es self invoked function, la traducción al español podría ser funciones auto llamadas o autoejecutables y son funciones que se ejecutan inmediatamente en el momento en que se definen.

1 2 3

(function () { alert("hola, soy una función que no necesita ser llamada"); })();

La diferencia en la sintaxis es el doble conjunto de paréntesis, como nemotecnia para recordarlas este es un buen truco:

1

(funcion (){})(autollamado)

Las funciones autoejecutables son muy útiles para crear closures y definir objetos bajo el patrón módulo, ambas técnicas las estudiaremos a continuación.

Closures Las variables globales son un peligro, por lo mismo uno busca encapsular las variables peligrosas, en javascript eso se puede hacer a través de un closure. Vamos a ver un ejemplo práctico de esto. Digamos que queremos generar un clicker virtual, estos son unos dispositivos físicos que cada vez que uno les presiona un botón aumentan en uno. Eso lo podríamos resolver con este simple código.

1 2 3 4

var i = 0; var click = function(){ i = i + 1 }

El problema de hacerlo de esta forma es que en otra parte del código yo podría reescribir la variable i por error, por ejemplo dentro de un for, una solución sería ocupar un nombre más complejo, pero un proyecto grande podría tener miles de líneas de código y no queremos dejar las cosas a la suerte. Para ilustrarlo mejor veamos un ejemplo de este problema con código.

1 2 3 4 5 6 7 8 9 10 11 12

console.log(i) click(); console.log(i) click(); console.log(i)

// i = 0 // i = 1 // i = 2

for (var i = 0; i 1 console.log(index()) // -> 2 console.log(index()); // -> 3

En el ejemplo anterior la variable contador quedó encapsulada dentro de la función click. Esta variable no puede ser accedida desde fuera, solo desde dentro o de una función definida dentro, entonces lo que hacemos es aprovechar nuestra función para que devuelva una nueva función que modifique el valor. Dejando de lado las definiciones formales, se puede decir que closure es la capacidad de poder guardar datos dentro de una función para que estos puedan ser utilizados en el futuro.

Closure con función autoejecutable El código que hicimos puede ser mejorado de forma que el usuario no tenga que asignar click a index para luego llamarlo, podríamos hacer simplemente click, para eso aprovecharemos el truco de autollamado que aprendimos recientemente.

1 2 3 4 5 6 7 8 9 10 11

var click = (function(){ var contador = 0; return function (){ contador = contador + 1; return contador; }; })() console.log(click()); // -> 1 console.log(click()); // -> 2 console.log(click()); // -> 3

De esta forma click se ejecuta automáticamente, parte en cero y cada vez que es llamado aumenta el contador en uno.

Capítulo 9

Objetos En javascript existe un super tipo de variable llamado objeto, estos nos ayudarán a crear todos los tipos de datos que necesitemos. Los objetos se parecen mucho a los arrays, pero se definen con llaves.

1

objeto = {}

A diferencia de los arrays los objetos no tienen un índice numérico, tienen uno con nombre, pero ese nombre no es automático, hay que agregarlo de la siguiente forma:

1

objeto = {nombre_indice: valor}

Nota al margen: En javascript casi todo es un objetos, excepto null y undefined.

Creando objetos Hay dos formas de crear objetos, la primera es a través de los {} como vimos previamente, la segunda es utilizando el operador new.

1

var objeto = new Object();

Agregando propiedades a un objeto. Los índices con nombre dentro de un objeto se llaman propiedades, podemos agregar propiedades nuevas de dos formas.

1 2

var mueble = new Object(); // o mueble = {} mueble.color = "café";

3

mueble['altura'] = "2";

Las dos formas son válidas y correctas. Las propiedades de los objetos son como variables, por lo tanto pueden contener datos, funciones e incluso otros objetos.

1 2 3 4 5 6 7 8 9 10 11 12 13

// Objeto 1 var motor700 = {cilindrada: 700, tiempos: 4}; // Objeto 2 que contiene al objeto 1 var motocicleta = { marca:'Ducati', motor:motor700, acelerar: function(){ console.log('Acelerar a fondo'); }}; motocicleta.acelerar(); // -> 'Acelerar a fondo'

Cuando un objeto tiene una función a esta función se le denomina método, cuando tiene una variable se le denomina propiedad

Leyendo las propiedades de un objeto Se realiza de la misma forma que agregarlas, en el ejemplo de la moto podemos obtener la marca con motocicleta.marca o motocicleta['marca']

Borrando propiedades de un objeto Para borrar una propiedad de un objeto se utiliza la instrucción delete. En el ejemplo de la moto:

1

delete motocicleta.marca;

Cuidado con el borrado de elementos de array Es posible borrar un elemento de un array con la instrucción delete, pero debemos tener cuidado, porque cambia el valor por undefined.

1 2 3 4 5

var array = [1,2,3,4]; delete array[2]; console.log(array) ; // [1, 2, undefined × 1, 4]

Se debe ocupar el método splice.

El operador this Es posible dentro de un objeto obtener el valor de una de sus propiedades utilizando el operador this, por ejemplo en el caso de la motocicleta, el método acelerar podría mostrar su marca gracias al operador como se muestra en el siguiente ejemplo.

1 2 3 4 5

var motocicleta = { marca:'Ducati', acelerar: function(){ console.log( this.marca + ' Acelerando a fondo'); }};

En el ejemplo anterior this.marca se transformará en ‘Ducatti’ y el método imprimirá ‘Ducatti Acelerando a fondo’

El operador this y el objeto window ¿Que sucede si utilizamos el operador this fuera del scope de un método, por ejemplo en el caso de una función o directamente en la consola. En ese caso obtendremos el objeto window que representa al tab abierto del navegador y contiene información como el ancho y el alto de la página, el HTML completo e información de todas las variables registradas. Cuando uno asigna el valor a una variable esa variable se convierte en una propiedad del objeto window,

probemos que esta afirmación es cierta. creemos dos variables y luego busquémoslas dentro del objeto window.

1 2 3 4

var a = 6 var ab = 5 var ab = 6 console.log(this)

Como podemos en la imagen las variables son todas propiedades del objeto window.

Pero, ¿qué pasa si registramos un objeto vaca con la propiedad moo?

1 2

vaca = {moo:'moo'} console.log(this)

En este caso veremos que la propiedad de vaca moo no está registrada dentro de window si no que está registrada dentro de la vaca misma. Como regla de buena costumbre debemos evitar sobrecargar el objeto window de propiedades, en lo posible solo deberíamos agregar un par de objetos básicos necesarios.

Mutabilidad en los objetos

Los objetos al igual que los arrays son mutable.

1 2 3 4

objeto1 = {"soy_mutable": "no"} objeto2 = objeto1 objeto2.soy_mutable = "si" console.log(objeto1)

Ahora que ya sabemos que son los objetos podemos definir mejor que es la mutabilidad, y es que las propiedades puedan ser cambiadas por el resultado de una operación o del llamado de un método.

Copiando un objeto Javascript no soporta copia de objetos directamente, al asignar un objeto a otro estamos copiando la referencia y no el objeto. Utilizando el siguiente truco podemos copiarlo:

1 2 3 4 5 6 7 8 9 10

var bob = { name: "Bob", age: 32 }; var bill = (JSON.parse(JSON.stringify(bob))); bill.name = "Bill"; console.log(bob); console.log(bill);

Array de Objetos con Filter, Map y Reduce Combinar arrays con objetos es una combinación muy poderosa para manejar los datos en Javascript. Para operar de forma eficiente sobre los datos ocuparemos los métodos filter, map y reduce. Para este ejemplo utilizaremos un array con mascotas, cada mascota tendrá nombre, tipo y edad.

1 2 3

var mascotas = [ { nombre: 'Bobby', tipo: 'perro', edad: 12 }, { nombre: 'Pinky', tipo: 'gato', edad: 14 },

4 5 6

{ nombre: 'Campeón', tipo: 'perro', edad: 4 }, { nombre: 'Doggy', tipo: 'perro', edad: 11 }, ];

Si se quisiera tener un arreglo con los nombres de perros mayores a 10 años.

1 2 3 4 5 6 7 8 9 10

var perrosMayores = mascotas .filter(function(mascota){ return mascota.edad >10 && mascota.tipo == 'perro'; }) .map(function(mascota){ return mascota.nombre; }); console.log(perrosMayores); // -> ['Bobby','Doggy']

Ahora vamos a sumar la edad de todos los perros.

1 2 3 4 5 6 7 8 9 10 11 12 13

var totalEdadPerros = mascotas .filter(function(mascota){ return mascota.tipo == 'perro'; }) .map(function(mascota){ return mascota.edad; }) .reduce(function(anterior,actual){ return anterior+actual; },0); console.log(totalEdadPerros); // -> 27

Preguntas 1. ¿Qué significa que un objeto sea mutable? 2. ¿Cuál es la diferencia entre map, reduce y filter? 3. ¿Dentro de un objeto a que hace referencia this?

4. ¿Fuera de un objeto, a que hace referencia this?

Patrón de diseño Módulo El patrón de diseño módulo consiste en devolver un objeto literal con los métodos públicos y todo el resto queda encapsulado dentro del objeto. Para construir uno tenemos que recordar las closures en javascript y como estas pueden encapsular variables, de manera que estas queden protegidas de ser modificadas accidentalmente, además revisamos lo que son los objetos en javascript y que estos pueden contener otras variables. La pregunta que se pueden hacer algunos en estos momentos es cómo puedo encapsular las variables en un objeto. Esto en programación se llama habitualmente variables privadas y unos de las maneras más utilizadas en javascript es un patrón de diseño llamado módulo. Volvamos a nuestro ejemplo de closure:

1 2 3 4 5 6 7

function generarIndice(){ var contador = 0; return function(){ contador = contador + 1; return contador; }; };

Un gran problema de este índice es que no puedo saber cual es el último valor generado, si llamo a esta función voy a aumentar este contador. Sin embargo, puedo modificar esta función para que retorne un objeto en vez de una función.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

function generarIndice(){ var contador = 0; var obtIndice = function(){ contador = contador + 1; return contador; }; var ultIndice = function(){ return contador; }; return {obtenerIndice: obtIndice, ultimoIndice:ultIndice}; }

16 17 18 19 20 21 22 23 24

var miIndice = generarIndice(); var primero = miIndice.obtenerIndice(); console.log(primero) // -> 1 var segundo = miIndice.obtenerIndice(); console.log(segundo) // -> 2 console.log(miIndice.ultimoIndice()); // -> 2

De esta manera puedo obtener el último valor sin tener que modificar el contador y este queda totalmente protegido. Por último, en javascript al existir variables globales es preferible nombrar variables lo mínimo posible, de manera de no entrar en conflicto con otros códigos. Es por esto que se sugiere en este caso crearlo con función anónima, con lo anterior nuestro código quedaría de la siguiente manera:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

var miIndice = (function(){ var contador = 0; var obtIndice = function(){ contador = contador + 1; return contador; }; var ultIndice = function(){ return contador; }; return {obtenerIndice: obtIndice, ultimoIndice:ultIndice}; })();

El ejemplo anterior es el patrón de diseño módulo, muy popular en este lenguaje.

Capítulo 10

Prototipos Todos los objetos en javascript descienden del objeto Object, por lo tanto todos los objetos heredan las propiedades de Object.prototype. Esto quiere decir que cada vez que se crea un objeto, estos tendrán automáticamente todas las funcionalidades del prototipo de Object. Con la propiedad prototype se pueden crear o sobreescribir sus propiedades en cualquier momento. El método toString() pertenece al prototipo Object y permite convertir cualquier objeto en un string, como se puede inferir de su nombre. Vamos a ver cómo se pueden sobrescribir los métodos de un prototipo en javascript, incluso del objeto base Object.

1 2 3 4 5 6 7 8 9 10 11

var colores = ['rojo', 'azul', 'verde', 'amarillo']; colores.toString(); // -> 'rojo,azul,verde,amarillo' Object.prototype.toString = function(){return "Hola"}; colores.toString(); // -> 'Hola' var b = {}; b.toString(); // -> 'Hola'

De este ejemplo anterior se puede inferir al menos tres cosas: 1. Cada vez que se modifica el prototipo de un padre automáticamente se modifican todas las propiedades heredadas de un hijo. 2. Estas propiedades (en este caso un método) se almacenan sólo una vez en memoria para todos los objetos. Por lo tanto se convierte en una herramienta muy poderosa cuando existen muchos objetos con la misma funcionalidad y es necesario disminuir el uso de memoria ram. 3. Puede llegar a ser altamente peligroso la modificación de los prototipos de los objetos y bajo ninguna circunstancia es recomendable modificar el prototipo Object.

Ahora revisemos ejemplos más “seguros”, voy a crear el objeto Persona y le voy a agregar métodos a su propiedad prototype. Como revisamos antes para acceder propiedades de un mismo objeto hay que ocupar this. Para crear este objeto lo voy a “construir” con una función.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

// función “constructora” function Persona(nombre){ this.nombre = nombre; } //Voy a agregar un método al prototipo Persona Persona.prototype.saludar = function(){ return 'Hola, mi nombre es ' + this.nombre; }; //Creo una nueva instancia de Persona con “new” var pancho = new Persona('Pancho'); console.log(pancho.saludar()); // -> 'Hola, mi nombre es Pancho' Ahora voy a crear al objeto Hombre que llama al constructor de Persona //Creo un nuevo objeto Hombre que llama // al constructor de Persona function Hombre(nombre){ Persona.call(this,nombre); this.sexo = "Hombre"; } var juan = new Hombre('Juan'); console.log(juan.nombre); // -> 'Juan' console.log(juan.sexo); // -> 'Hombre' console.log(juan.saludar()); // -> undefined is not a function

Recibimos este error porque el objeto Hombre sólo llamó al constructor Persona, para que herede los métodos se su prototipo es necesario hacerlo explícitamente.

Capítulo 11

Javascript y HTML Para esta sección del curso será empezar a trabajar con el editor de texto puesto que no solo tendremos que escribir código javascript, además tendremos que escribir código HTML.

Estructura de un proyecto web con javascript. Es importante tener crear una carpeta para cada uno de nuestros proyectos web, dentro de esta carpeta tendremos nuestro archivo index /nombre-proyecto/index.htm ademas dentro de la carpeta crearemos una subcarpeta llamada js, y dentro de esta pondremos nuestros archivos javascripts. Cabe mencionar que hay gente que crea dos carpetas, una llamada assets para sus javascript, css e imágenes y otra llamada vendors por los javascript de terceros.

Nuestro index.html 1 2 3 4 5 6 7 8 9 10 11 12



Además debemos crear la carpeta js dentro del proyecto y el archivo main.js

Si al cargar la página obtenemos un error del tipo:

1 2

GET file:///Users/gonzalosanchez/proyectos/librojs/ js/main.js net::ERR_FILE_NOT_FOUND

entonces significa que no hemos creado el archivo main.js o que no lo pusimos dentro de la carpeta js.

Manipulando el DOM ¿Cómo se llamaba el objeto maestro de una página web?, si contestaste Window estás en lo correcto. Este objeto tiene una interesante propiedad dentro llamada document, este contiene el documento completo de la página web y claro si es parte de las propiedades de un objeto de javascript lo podemos modificar.

document Vamos a agregar un div vacío a nuestra página web

1 2 3 4 5 6 7 8 9 10 11 12 13

Contenido ...

Utilizando document podemos obtener el div y modificarlo de la siguiente forma:

1

document.getElementById("modificable")

Para probarlo mostraremos en consola el div dentro de nuestro archivo main.js

1

console.log(document.getElementById("modificable"))

Si el elemento existe obtendremos el tag si no obtendremos null, si tienes el elemento dentro del html pero aún así obtienes null hay un par de posibles causa, la primera es que no hayas guardado el código y luego que no hayas recargado la página pero la tercera es la más interesante, que hayas cargado el script después de la etiqueta.

¿Que es el DOM? DOM es el acrónimo de Document Object Model, no es une el HTML pero tiene mucho que ver con el. El DOM es la interfaz de acceso para crear HTML válido, permite agregar, modificar y borrar contenido. En DOM todo es un nodo, el documento, todos los atributos html, todos los elementos de html, etc, El objeto documento que vimos previamente es el nodo raíz, pero sólo se convierte en el nodo raíz una vez que el documento está cargado.

El orden importa Es por eso que los scripts que modifican el DOM deben ser cargado al final, porque los nodos para poder referenciarlos, añadirle atributos, modificarlos, o borrarlos primero necesitan estar cargados. Lo anterior implica que si la instrucción document.getElementById("modificable") se alcanza antes de que se defina entonces obtendremos null, la solución para evitar este tipo de errores es ser consciente de en que momentos estamos buscadondo y modificando el DOM y que definitivamente no podemos hacerlo antes de definirlo.

Modificando el DOM Ya sabemos como recuperar etiquetas del DOM ocupando javascript, ahora aprenderemos como modificar estos elementos y eso lo podemos utilizar cambiando la propiedad innerHTML

1 2

div_modificable = document.getElementById("modificable"); div_modificable.innerHTML = "nuevo contenido";

No solo podemos cambiar el texto, además podemos cambiar el CSS

1 2

div_modificable.style.color = "red"; div_modificable.style.fontSize = "40px";

Obteniendo los elementos de HTML por clase Para estudiar este caso vamos a construir una sencilla página web con varios párrafos, cada uno de estos tendrá la clase párrafo

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Contenido1 Contenido2 Contenido3 Contenido4

Luego en nuestro script podemos obtener todos los párrafos con document.getElementsByClassName("parrafo") pero a diferencia de getElementById este método devuelve un Array Entonces … ¿como cambiamos el contenido o el estilo de cada uno de los párrafos? Podemos iterar sobre los elementos con for.

1 2 3 4

var parrafos = document.getElementsByClassName("parrafo"); for (var i = 0; i < parrafos.length; i++){ parrafos[i].innerHTML = "Super Contenido " + i; }

o podemos hacerlo con forEach, (recordar que no funciona en todos los navegadores)

1 2 3

parrafos.forEach(function(parrafo){ parrafo.innerHTML = "Super Contenido " + i; })

Eventos en Javascript En javascript es posible registrar eventos, cuando la condición del evento se cumple el código javascript es ejecutado, por ejemplo podemos hacer que un div que dispare una alerta al ser clickeado.

Click Para eso utilizaremos un estilo para darle ancho y alto a los divs

1 2 3 4 5 6 7 8

.caja { width:50px; height:50px; margin:5px; background-color: blue; float:left; }

y luego dentro del código HTML:

1 2 3 4 5



De esta forma al recargar el sitio y al hacerle click a la primera caja veremos algo como:

Desafío Ahora intenta cambiar el color de una caja al hacerle click.

No avances hasta resolver el ejercicio, más abajo aparece la respuesta.

Don’t repeat yourselve Es bastante posible que hayas planteado una solución de este tipo.

1 2 3 4 5

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF