Gestión de modelos con “bundle”

Acabo de descubrir un sistema para gestión de todo tipo de código y dependencias, que no utilizaba para las paginas web. Se llama Webpack

Este bundle https://webpack.js.org permite tener el código mas ordenado, optimizar ancho de banda y gestionar bien las dependencias. Pero el futuro ya esta llegando con ECMAScript, que ya esta soportado por navegadores, así que solo es una herramienta buena pero supongo que dentro de un tiempo ya estará obsoleta.

Manipulación de elementos en JavaScript

Manipulación dinamica. BOM vs DOM en JavaScript

  • Objeto window representa una o varias ventanas abierta por navegador.
  • Podemos acceder al historico de navegación.
  • Internet Explorer aún soporta document.all, aún que indica en ultimas versiones que no lo hace.
  • opener: devuelve una referencia a la ventana desde la cuál se ha abierto.
  • pageXOffset y pageYOffset. Posiciones de desplazamiento para dejar un objeto siempre visible.
  • Por seguridad codigo JS tiene que coincidir dominio y puerto para funcionar.
  • postMessage para comunicación entre ventanas.
  • find: busca el texto indicado en el documento actual y destaca los fragmentos encontrados.
  • objeto history (length – número de entradas): back, forward, go.
  • objeto navigator (appVersion, userAgent, javaEnabled(), plugins, mimeTypes, platform, cookieEnabled).
  • screen (tamaños de pantalla, dpi’s, etc).
  • document.Open/Close y writeln para mostrar texto nuevo.
  • querySelectorAll devuelve coleccion estatica que es mas lento que colecion dinamica getElementBy*.
  • Mejor no usar += en innerHtml. Sino recargamos la pagina varias veces.
  • Modificación del DOM: createElement, createtextNode, cloneNode, appendChild, insertBefore, removeChild, replaceChild.
  • Añadir nuevo elemento: document.body.appendChild(nuevoDiv);

Programación Orientada a Objetos (POO) en JavaScript

Descripción de POO: como crear clases, herencias, polimorfismo, etc. en JavaScript

  • Clase es definicion como tiene que ser.
  • Objeto es una instancia de la clase con valores aplicados y particulares.
  • En JS no existen interfaces.

Los tres pilares básicos de la Programación Orientada a Objetos son:
A. Encapsulación.
B. Herencia.
C. Polimorfismo.

2.1. Redefiniendo objetos genericos:
Crear objeto:

var marcianito = new Object(); // Creamos objeto
marcianito1.name = “invasor del espacio #1”; // Se crea nueva propiedad y se asigna valor a ella
marcianito1.color = “Azul”;
marcianito1.x = 100;
marcianito1.y = 20;
marcianito1.disparos = 30;
marcianito1.disparos++; // Incrementamos valor de propiedad

Crear metodos:
marcianito1.disparar = function () {
this.disparos–;
alert(this.name + ” ha disparado.”);
}

Uso de metodos:
marcianito1.disparar();

2.2. Sintaxis JSON para objetos (JavaScript Object Notation). No es muy util para hacer POO.

var marcianito1 = {
name : “invasor del espacio #1”, // Uso de “:” para asignacion de valor
color : “Azul”, // Uso de “,” despues de cada propiedad si despues hay otra
x : 100,
y : 20,
disparos : 30,
disparar : function () {
this.disparos–;
alert(this.name + ” ha disparado.”);
}
}

marcianito1.disparar(); // Funciona exactamente igual.

2.3. Patrón factoría

Creando objetos usando una funcion.

function crearMarcianito(elNombre, elColor, posX, posY, disparosIniciales) {
return {
name : elNombre,
color : elColor,
x : posX,
y : posY,
disparos : disparosIniciales,
disparar : function () {
this.disparos–;
alert(this.name + ” ha disparado.”);
}
};
}

var marcianito1 = crearMarcianito(“Invasor #1”, “Azul”, 0, 0, 30);
var marcianito2 = crearMarcianito(“Invasor #2”, “Verde”, 100, 300, 50);
alert(marcianito1.name);
alert(marcianito2.name);

  1. “new” para crear objetos. Llama al constructor que contiene todas las clases.
    “instanceof” para identificar la clase de objeto.
    3.1. Constructores reales de objetos:
    “this.” para crear propiedades de propio objeto. Ej: function Marcianito(elNombre,…){ this.name = elNombre; }
    “new”. Ej.: var item = Marcianito(“Invasor #1”,…);
    3.2. Fundamentos de la variable especial this.
  • Depende desde donde se llama al “this.” le da un valor u otro.
  • “this.” en constructor (en llamada “new”) – acceso a propio objeto para crear propiedades. JS al llamar a funcion con “new”, pasa al constructor nuevo objeto vacio.
  • Si no ponemos “new”, “this.” no sera nuevo objeto y no se asignaran propiedades. No devolvera objeto esta funcion. Dentro de funcion “this.” representa que es la ventana del navegador. Es objeto global del ejecutor del codigo, en navegadores es ventana.
  • Si no ponemos “this.”, ni “var”, se definen propiedades globales como si se llaman con “this.”.
  • Objetos se escriben con PascaleCase (Primera letra mayuscula).
    3.3. Determinando el tipo del objeto:
    “typeof(item)” nos devuelve el tipo, en caso de objetos devuelve “object”, porque no son objetos nativos de JS.
    Cuando llamamos “new” nos crea una propiedad “item.constructor”. En esta propiedad esta todo el codigo del constructor.
    Si comparamos item.constructor == Marcianito. Y nos indica si constructor es igual que función.
    Si hacemos (marcianito1 instanceof Marcianito) nos indicara “true” porque nos indica que marcianito1 es una instancia del constructor Marcianito.
    Si hacemos (marcianito1 instanceof Object) tambien es “true” porque todos objetos heredan de Object.
  1. Prototipos
    4.1. Funciones compartidas en prototipos.
  • Es ineficiente crear cada vez funciones dentro asi:
    marcianito1.disparar = function () {
    this.disparos–;
    alert(this.name + ” ha disparado.”);
    }
  • Podemos asignar al metodo de la clase una funcion no anonima. Pero no es mejor forma de hacer lo.
    Ej.: marcianito1.disparar = marcianoDisparar;
  • En cambio podemos usar prototipo “Marcianito.prototype” (en este caso no se utiliza “this.”). Si le asignamos una función, sera disponible para todas las instancias de la clase. Ej.: Marcianito.prototype.disparar = function () {…}
  • Para no redefenir la misma funcion en cada llamada al constructor, comprobamos si ya existe: if(!Marcianito.prototype.disparar) { Marcianito.prototype.disparar = function() {} };
  • Con prototype podemos definir funciones a clases que ya existen. Por ejemplo queremos tener un check si es numerico en cadenas. Extendemos clase “String” y anyadimos con propotipo nueva funcionalidad. Ej.: String.prototype.isNumeric = function () {…}
    4.2. Búsqueda de miembros y cadena de prototipos:
  • No se definen metodos con prototipos en todas las clases instanciadas de un tipo en concreto. Se sigue una cadena de busqueda:
    A) Primero se busca en el objeto.
    B) Si no está se busca en su prototipo
    C) Si no está se busca en el prototipo del prototipo (de haberlo) y así sucesivamente.
    D) Si no se encuentra en el último prototipo entonces se produce un error porque no existe el miembro buscado.
  • Es muy importante que “this.” sigue apuntando al objeto original, aún que se llama desde “prototype”.
  • Prototipo es un objeto, asi que puede tener su propio prototipo.
  • “Shadow”: Podemos con prototipo ocultar en nivel inferior una funcionalidad superior. Ej: Marcianito.prototype.toString = function() { return this.name + ” – ” + this.color; };
  • Para crear variables estaticas compartidas entre todos objetos de la misma clase: Marcianito.prototype.Propiedad1 = 1; No es muy recomendable su uso.
  • Propiedad “proto” apunta a la clase prototipo. Normalmente no tenemos que tocarla.
  1. Controlando el valor de contexto con call y apply:
  • Valor de “this.” depende del contexto desde cual lo llamamos. Pero lo podemos modificar.
  • Usar metodos “call” y “apply” para pasar contexto como primer argumento y parametros (call) o matriz (apply). Ej.:
    function asignarNombreYEdad(nombre, edad) {
    this.Nombre = nombre;
    this.Edad = edad;
    }
    var miObjeto = new Object();
    asignarNombreYEdad.call(miObjeto, “Pepe”, “40”); // Llamada a la función usando call toma primer parametro como contexto (this)
    asignarNombreYEdad.apply(miObjeto, [“Pepe”, “40”]); // Lo mismo que “call”, pero se le pasan parametros en una matriz
    alert(miObjeto.Nombre + ” – ” + miObjeto.Edad);
  • Metodo “bind” igual que “call” pero no ejecuta directamente, sino crea una referencia a funcion para una llamada mas tarde con su contexto y parametros.
  1. Herencia
    6.1. Herencia: Encadenamiento de prototipos
  • No se soporta de manera nativa en JS.
  • Formas de herencia: simple encadenado de prototipos, robo de constructores, herencia por combinación, herencia prototípica (inventado por Douglas Crockford, conocido programador JavaScript), herencia parasitaria.
  • Si hacemos que el prototipo de nuestra clase sea una instancia de otra, entonces la nueva clase dispondrá de los mismos miembros que la original. Ej.:
    function ClaseBase()
    {
    this.Nombre = “”;
    ClaseBase.prototype.mostrarNombre = function () {
    alert(this.Nombre);
    }
    }
    function ClaseDerivada()
    {
    this.Apellidos = “”;
    }
    ClaseDerivada.prototype = new ClaseBase();
    ClaseDerivada.prototype.constructor = ClaseDerivada; // Importante asignar el constructor de esta manera

var cd = new ClaseDerivada();
cd.Nombre = “Perico”;
cd.Apellidos = “de los Palotes”;
cd.mostrarNombre();
alert(cd instanceof ClaseDerivada);
alert(cd instanceof ClaseBase);

No es muy recomendable esta tecnica antigua, porque es propensa de errores y no es muy comoda.

6.2. Robo de constructores y sustitución de prototipos:

  • Bibliotecas utiles: jQuery, Dojo, Prototype, ExtJS.
  • Herencia aconsejable en JS: robo de constructores con sustitución de prototipos. Consiste en llamar al constructor de la clase base desde el constructor de la derivada, pasándole como contexto el objeto que se está creando. Ej.:
    function ClaseBase(nom)
    {
    this.Nombre = nom;
    ClaseBase.prototype.mostrarNombre = function () {
    alert(this.Nombre);
    };
    }
    function ClaseDerivada(nom, apell)
    {
    ClaseBase.call(this, nom);
    this.Apellidos = apell;
    }
    ClaseDerivada.prototype = new ClaseBase();
    ClaseDerivada.prototype.constructor = ClaseDerivada;

6.4. Detalles internos sobre creación de objetos
Ej.:
function NEW(fConstructora){
var nObjeto = {
proto‘: fConstructora.prototype
};
return function(){
fConstructora.apply(nObjeto, arguments);
return nObjeto;
};
};

  • Se asigna prototipo.
  • Se devuelve funcion como objeto.
    Constructor normal:
    function Animal(sNombre, nPatas) {
    this.nombre = sNombre;
    this.patas = nPatas;
    }
    var bicho = new Animal(“Perro”, 4);
    console.log(bicho);
    Con nuestro constructor:
    var bicho2 = NEW(Animal)(“Canario”, 2);
    console.log(bicho2);
    Herencia habitual:
    function Gato(sNombre) {
    Animal.call(this, sNombre, 4);
    }
    Gato.prototype = new Animal();
    Gato.prototype.constructor = Gato;
    var gato1 = new Gato(“Patucas”);
    console.log(gato1);
    Herencia con nuestro constructor:
    var gato2 = NEW(Gato)(“Calcetines”);
    console.log(gato2); //Idéntico!

6.5. Herencia: Detalles importantes a recalcar

  • Clase puede derivarse de otra clase.
  • Los prototipos no se utilizan para instanciar objetos, sino en si son objetos.
  • Si objeto no tiene propiedad, JS busca en sus prototipos padres. Uso de cadena de prototipos.
  • Clase B que herada de clase A no tiene su constructor por defecto. Hay que asignar lo (robar), pero no siempre es obligatorio.
  • Propiedades prototype y proto no son iguales. Uno es para definicr cosas, otro es para ver el objeto. Normalmente objetos no disponen de propiedad prototype cuando depuramos, prototype apunta a objeto patron, en cambio proto al objeto concreto. “prototype” es propiedad solo de tipos nativos de JS.
  • Clase en JS en realidad en una funcion constructora.
  • Cuando una función se usa con la palabra clave new delante, JS crea un objeto vacío, asigna como prototipo (en proto) lo que haya en la propiedad prototype de la función y la llama estableciendo this a este nuevo objeto.
  • ClaseDerivada.prototype.constructor = ClaseDerivada es para asociar y saber en futuro el tipo de objeto/funcion constructora. Sino tambien funciona, pero no sabremos el tipo. O tambien para instanciar otra clase sin igual sin saber cual es la clase exacta con .constructor. Esta propiedad no existe si creamos objeto con JSON, no es obligatoria para objetos, ya que JS no la utiliza.

6.6. Herencia: Uso práctico de prototype

  • Propiedad prototype contiene funcion que se utilizara para crear objetos que se asignaran a la propiedad “proto“.
  • El prototipo es el mismo para todos los objetos de la misma clase.
  • Podemos aprovechar prototipo para crear metodos y propiedades “estaticas”.
  • Formas de crear “prototype”:
    A. Gato.prototype = new Animal(); // Podemos tener problemas con propiedades que no inicializamos
    B. Gato.prototype = new Animal(“Patron”, 0); // evitamos problemas de que haya propiedades sin inicializar
    C. Gato.prototype = object.Create(Animal.proptotype); // variante moderno, utilizando Object.create, crea objeto sin inicializar con prototipo asignado, no se llama al constructor de la clase base. Mas optimizado por no tener objetos no inicializados. Es el mas recomendado si IE>8
  • Asignamos construcor “Gato.prototype.constructor = Gato;” para coherencia y para crear hijos:
    Animal.prototype.procrear = function(){
    // Creacion normal
    return new Animal(this.nombre + ” – Hijo”, this.patas);
    // Creacion usando constructor original y le asigna el tipo de objeto identico al del padre
    return new this.proto.constructor(this.nombre + ” – Hijo”, this.patas);
    };
    gatito1 = gato1.procrear();
    console.log(gatito1);
  • Nuevas versiones de firefox muestran “proto” como “”, pero realmente es “proto“.

7.0. Encapsulación en JavaScript

  • La encapsulación o encapsulamiento es una característica de los lenguajes orientados a objetos que consiste en que las clases pueden definir miembros privados, ocultos al exterior, y que solamente pueden ser cambiados a través de los métodos establecidos a tal efecto.
  • En JS es dificil. Ya que propiedades son publicas.
  • clausuras o closures. Es una función que es evaluada en un determinado ámbito pero que tiene acceso también a variables que están ubicadas en un ámbito diferente. Son como un puente entre dos mundos.
    Ej.:
    function pruebaClosure() {
    var loc = “¡Hola closure!”;
    this.muestraMensaje = function () {
    alert(loc);
    };
    }
    var obj = new pruebaClosure();
    obj.muestraMensaje(); //Muestra el mensaje de saludo
  • La verdadera regla de acceso a variables es que una línea de nuestro código sólo puede acceder a variables que tengan un ámbito mayor o igual que el suyo propio. En este caso “loc” pertenece a un ambito mayor.
  • una jerarquía donde los niveles inferiores siempre tienen acceso a los superiores.
  • lo que representan son funciones que tienen acceso a una serie de variables liberadas ya en su propio ámbito original, pero que quedan confinadas (clausuradas) en el ámbito de la función que las utilizará más tarde, fuera de ámbito.

Ejecución diferida de funciones gracias a las clausuras
function concatenar(s1) {
return function(s2) {
return s1 + ‘ ‘ + s2;
};
}
var diHola = concatenar(“Hola”);
alert( diHola(“visitante”) );

  • hemos definido una función que permite asignar valores para ejecución retardada.
  • lo que tenemos en la variable diHola es una función pre-parametrizada y lista para ser utilizada.

Ejemplo de uso en setInterval y setTimeOut cuando queremos pasar parametros a la funcion, en lugar de llamar a una funcion desde otra funcion (solución fea pero comun).
function moverElemento(elto, x, y)
{
return function(){
elto.style = “position:absolute; left:”+ x + “;top:” + “y;”;
};
}
var mover = moverElemento(getElementById(“miDiv”), 0, 0);
setTimeout(mover, 500);

  • Para mantener ambito al principio de funciones escribimos como primera linea, es importante para si hay subfunciones:
    var that = this; // O tambien se utiliza “var self = this;”

7.2.1. Prototipos accediendo a variables de ámbito: un error grave

  • Cuidado que objetos no tengas atributos compartidos:
    function Marcianito(elNombre, elColor, posX, posY, disparosIniciales) {
    var that = this;
    var _name = elNombre;
    Marcianito.prototype.getName = function(){
    return _name.toUpperCase() + ” (” + that.color + “)”;
    };
    }
  • Aqui el problema esta en que se redefine funcion de prototipo “getName”. Esta funcion del prototipo queda atada a propiedades del ultimo ambito que la llama. De esta manera podemos crear “variables privadas estáticas”.
  • Para metodos de clausura no hay que utilizar prototype, sino crear metodos con this. Ej: this.getName = function(){…_name…that.color…;
  • Las funciones del prototipo no pueden acceder a variables de instancia (como _name o that en el ejemplo).
  • Funcion completa de ejemplo:
    function Marcianito(elNombre, elColor, posX, posY, disparosIniciales) {
    var that = this;
    var _name = elNombre;
    this.getName = function(){
    return _name.toUpperCase() + ” (” + that.color + “)”;
    };
    this.setName = function (nombre) {
    _name = nombre;
    };
    this.color = elColor;
    if (posX < 0) posX = 0; if (posX > 100) posX = 100;
    this.x = posX;
    if (posY < 0) posY = 0; if (posY > 100) posY = 100;
    this.y = posY;
    if (disparosIniciales < 0) disparosIniciales = 0; if (disparosIniciales > 100) disparosIniciales = 100;
    this.disparos = disparosIniciales;
    if (!Marcianito.prototype.disparar) {
    Marcianito.prototype.disparar = function () {
    this.disparos–;
    //codigo para pintar el disparo
    alert(this.getName() + ” ha disparado.”);
    };
    }
    Marcianito.prototype.toString = function () {
    return this.getName() + ” – ” + this.color;
    };
    }

7.3. Verdaderas propiedades encapsuladas

  • En POO por regla general se entiende por propiedad a un miembro que utiliza el mismo nombre tanto para leer como para escribir.
  • defineGetter y defineSetter de Object para definir con que funcion escribir y leer propiedades. Integradas en Mozilla Firefox, Chrome, Safari y Opera, pero no en Internet Explorer. Mozilla ha decidido hacerlas obsoletas, no forman parte de estandar.
  • ECMAScript 5 introduce “método defineProperty”.
  • defineProperty(objeto, nombre, descriptor):
    A. El objeto sobre el que se va a definir la propiedad
    B. El nombre de la propiedad
    C. Un objeto descriptor que definirá mediante sus propiedades las características concretas que regirán el acceso a la propiedad.
    C1. value: el valor inicial.
    C2. get: leer valor.
    C3. set: almacenar valor.
    C4. writable: posible cambiar valor.
    C5. configurable: si podemos o no cambiar el tipo de descriptor.
    C6. enumerable: indica se es enum.
  • “delete” permite eliminar miembros de objetos.
  • Ejemplo de uso de defineProperty
    var objeto = new Object();
    Object.defineProperty(objeto, “nombre”,
    {
    value: “Mi nombre”,
    writable: true,
    enumerable: true,
    configurable: true
    }
    );
  • Otra forma de definir con JSON
    if (Object.defineProperty) {
    Object.defineProperty(this, “name”,
    {
    get: getName,
    set: setName
    });
    }
  • Si usamos value no podemos utilizar las funciones get y set, y viceversa.
  • variante denominada defineProperties (en plural) para definicion multiple:
    Object.defineProperties(objeto,
    {
    “Apellido1”: { value: “López”, writable:true, enumerable:true},
    “Apellido2”: { value: “Fernández”, writable: true, enumerable: true }
    }
    );
  • Podemos bloquear la modificación de un objeto con Object (preventExtensions, seal y freeze).
  • “preventExtensions” no deja añadir propiedades o metodos.
  • “sel” impide añadir, quitar, redefinir propiedades/metodos.
  • “freeze” sella objeto y conjela propiedades (si en descriptor usan “value”).
  • Para verificar estado de estos metodos isExtensible, isSealed y isFrozen.
  1. Reflexión: Inspeccionando los objetos
  • Técnicas de reflexión (miembros que tiene un objeto)
  • Nombres (for-in): for (var prop in marcianito1)
  • Acceso a valor: marcianito1[“disparos”] = 50;
  • Llamada a funcion: marcianito1[“disparar”]();
  • For-in no devuelve en mismo orden en diferentes navegadores. Propiedades sin definir pueden no aparecer. Ej.:
    function ResumeObjeto(obj) {
    var prop;
    var informe = “”;
    for (prop in obj) {
    informe += prop + “: ” + obj[prop] + “\n”;
    }
    return informe;
    }

Fechas en JavaScript

Trabajo con fechas y detalles importantes en JavaScript

  1. Conceptos basicos sobre el manejo del tiempo en informatica.
  • epoch – desde que fecha SO cuenta tiempo.
  • En Windows tiempo se mide en 10.000 ticks del procesador = 1 milisegundo.
  • .NET epoch 01.01.0001, SQL Server 01.01.1753, etc.
  • Ordenadores trabajan con numeros, no con fechas.
    2+2.1. La clase Date.
  • Diferencia entre fechas en milisegundos. Epoch 1/1/1970 a las 00:00:00 horas.
  • Al crear “new Date()” tendremos fecha actual.
  • .toLocaleDateString() convierte fecha en un string, aplicando formato de fecha local corta (ej: dd/MM/yyyy)
  • .toLocalTimeString() convierte en hora en un string, aplicando formato de hora local.
  • “new Date(0)” obtenemos fecha de referencia (epoch).
  • “new Date(1972,4,23)”. Creamos fecha 23 de mayo de 1972. IMPORTANTE, meses cuentan desde 0.
  • “new Date(72,4,22,21,0,0)”. Creamos fecha 22 de mayo de 1972 21:00:00. IMPORTANTE, meses cuentan desde 0, anyos de 2 caracteres representan 19XX.
  • Si en fecha ponemos valor mas que toca, lo suma a la fecha. “new Date(1972, 13, 10)” sera 10 de febrero del 1973, porque tiene exceso en el mes (+2). Podemos asi sumer dias, meses y anyos. Tambien podemos tener restar determinados elementos, ej: new Date(1972,2,-10) sera 20 de febrero 1972.
  • “new Date(“Feb 12, 2015 20:15:37 GMT+2″)” sera 12/02/2015 22:15:37.
  • Comprobar si es fecha: return (valor instanceof Date).
    2.2. TRUCO: Número de días de un mes cualquiera.
  • Pasar en parametro 0 en dia. Ej.: “new Date(anyo, mes+1, 0)”. Nos devolvera numero de ultimo dia del mes indicado. new Date(2012,2,0) sera 29 de febrero 2012. Acordar que 2 representa tercer mes del año.
    2.3. Las partes del tiempo.
  • getTime: obtiene solamente la parte correspondiente a la hora, rechazando la fecha. Devuelve el número de segundos transcurridos desde el 1/1/ 1970. Es útil para crear marcas de tiempo para ciertas aplicaciones especiales de comunicación con el servidor.
  • getDay: nos dice el día de la semana en el que nos encontramos, empezando a contar en domingo, que sería el día 0. De este modo el lunes sería el 1, el – martes el 2 y así sucesivamente.
  • getDate: obtiene el día del mes dentro de la fecha dada.
  • getMonth: devuelve el número correspondiente al mes contenido en el objeto Date. Se comienza a contar en 0, que correspondería al mes de Enero.
  • getYear: devuelve el año contenido en la variable de tipo fecha. Esta función tiene un comportamiento algo extraño puesto que devuelve 2 cifras para años – anteriores al 2000, y 3 cifras para años posteriores al 2000. Es decir, empieza a contar los años en el 1900. Así, para el año 1980 devolverá 80, para 2016 – devolverá 116 y para 1897 será el año -3 (negativo). Su uso no está recomendado y se prefiere la el método siguiente que es consistente en lo que devuelve.
  • getFullYear: funciona igual que el anterior, pero en este caso el año se devuelve siempre con las cuatro cifras correspondientes. Debemos usarlo – generalmente en sustitución de getYear, que se considera obsoleta.
  • getHours: permite obtener el valor de la hora en una variable Date, sin incluir la fecha actual, ni los minutos ni los segundos.
  • getMinutes: con este método conseguimos averiguar los minutos de la hora indicada.
  • getSeconds: permite obtener la parte correspondiente a los segundos en una variable de hora.
  • getMilliseconds: facilita el número de milisegundos después del segundo actual que está especificado dentro de una variable de tipo Date. Es decir, aunque la hora actual se muestre redondeada a 19:22:37, internamente hay unos cuantos milisegundos de precisión más que podemos obtener, por lo que sería por ejemplo 19:22:37:849 (siendo 849 los milisegundos a mayores que devolverá esta función).
    2.4. Formatos personalizados.
  • En formato español: return fecha.getDate() + “/” + fecha.getMonth() + “/” + fecha.getFullYear();
    2.5. Zonas y diferencias horarias.
  • Universal Coordinated Time, UTC o GMT (o Greenwich Meridian Time, hora en el meridiano de Greenwich). El UTC es mas preciso, pero se cree que UTC y GMT es lo mismo.
  • getUTCDay
  • getUTCDate
  • getUTCMonth
  • getUTCFullYear
  • getUTCHours
  • getUTCMinutes
  • getUTCSeconds
  • getUTCMilliseconds
  • Obtener la zona horaria actual: getTimezoneOffset. Indica horas de diferencia ente hora local y hora UTC. Diferencia horaria no son horas completas.
    2.6. Métodos de modificación de fechas:
  • setDate: Permite asignar un nuevo día del mes a la fecha contenida en una variable.
  • setMonth: Asigna un nuevo valor para el mes en la fecha contenida en la variable. Recuerda que los meses empiezan a contar desde 0 para enero.
  • setYear: Permite cambiar el valor del año en una fecha. Si se usan sólo dos dígitos como argumento se considerará un año dentro del rango 1900-2000.
  • setFullYear: idéntico al método anterior pero se deben especificar siempre los cuatro dígitos del año. Es más recomendable que la anterior. Este método permite especificar opcionalmente el mes y el día del mes como segundo y tercer parámetro respectivamente.
  • setTime: permite asignar una nueva hora pasando como argumento el número de milisegundos transcurridos desde la medianoche del 1/1/1970. No se utiliza demasiado por razones obvias.
  • setMilliSeconds: fija el número de milisegundos que pasan del segundo en la hora actual de una variable.
  • setSeconds: permite fijar el número de segundos actuales en la variable. Opcionalmente se pueden especificar también los milisegundos como segundo parámetro.
  • setMinutes: fija los minutos actuales en la hora contenida en una variable. Tiene como parámetros opcionales el número de segundos y el de milisegundos transcurridos.
  • setHours: nos permite fijar la hora actual para una variable tipo Date. Tiene como tres parámetros opcionales los minutos, segundos y milisegundos.
    O en UTC:
  • setUTCDate
  • setUTCMonth
  • setUTCFullYear
  • setUTCMilliSeconds
  • setUTCSeconds
  • setUTCMinutes
  • setUTCHours
    2.7. Operaciones con fechas
  • Comparaciones basicas: date1>date2, date2>=date1, date1==date2 (compara objetos, normalmente devuelve false, mejor usar ===).
  • Uso de “+” para fechas suma fechas en formato string.
  • Uso de “*” no aporta nada.
  • Uso de “-” da diferencias en milisegundos, muy util y funciona bien.
  • Saber diferencia en dias: difDias = diferenciaEnMilisegundos / (24 * 60 * 60 * 1000).
  • Saber diferencia en meses: difDias = diferenciaEnMilisegundos / (30 * 24 * 60 * 60 * 1000).
  • Obtener numero de milisegundos: Date.parse(fechaBase).
  • Sumar 5 dias a fecha: base.setDate(base.getDate() + 5). Luego para representar en fecha: new Date(base.setDate(base.getDate() + 5)).
  • Sumar 13 segundos a fecha: base.setSeconds(base.getSeconds() + 13). Luego para representar en fecha: new Date(base.setSeconds(base.getSeconds() + 13)).
  1. Temporizadores y cronómetros
  • Para ejecutar codigo a intervalos regulares de tiempo.
  • Los timeouts ejecutan codigo 1 vez.
  • Los interval ejecutan codigo varias veces cada X.
    Formato: tempID = setTimeout(“Rutina”, Tiempo); “Rutina” – (opcion 1) nombre de un procedimiento o función a ejecutar, Tiempo – valor en milésimas de segundo. (opcion 2) Rutina tambien puede ser cadena a ejecutar “alert(‘Hola’)” (se considera como mala practica). (opcion 3) Función anonima con codigo a ejecutar.
  • setTimeout: anota valor de tiempo y devuelve referencia al temporizador. Ej: var miId = setTimeout(“miFuncion()”, 2000);
  • clearTimeout: para cancelar antes de que se ejecuta. Ej: clearTimeout(miId);
  • setInterval: definir cada cuanto ejecutar una función. Ej: id = setInterval(“Mifuncion()”, 2000);
  • clearInterval: parar un interval para que no se ejecuta mas. Ej: clearInterval(id);
    A los “set..” podemos pasar todos parametros que queremos: setTimeout(Mifuncion, 2000, parametro1, parametro2…);
    Estos metodos no son de JavaScript, sino del navegador. En NodeJS los volvieron a implementar.
    3.1. La precisión de los intervalos de tiempo.
    Intentar evitar valores muy pequeños. Mejor por encima de 100 milisegundos.
    JavaScript solamente posee un hilo de ejecución (excluyendo web workers de HTML).
    setTimeOut y setInterval ejecutan en mismo hilo.
    Si proceso dura mas que tiempo entre intervalos se iran metiendo en cola para ejecutarse. Y en cola puede haber solo una tarea de cada tipo, resto se descartan.
    Para asegurar que se ejecuta funcion despues de haberse ejecutado: function periodica() { setTimeOut(periodica, 100); }
    var divreloj = null; // variable global. En un timer buscaremos este div solo una vez, para luego aprovecharse de que ya lo tenemos y no tenemos que volver lo a buscar.

Matrices en JavaScript

Importantes detalles sobre matrices en JavaScript

  1. Definición y uso básico de matrices (se numeran desde 0). Ej.: var arr = new Array() o “new Array(3)” o “[]” (si ponemos [3] es matriz con 1 elemento con valor 3); arr[0] = “coche”;
    arr.length – longitud de matriz. No solo leemos este valor, podemos escribir lo para redimencionar y nuevos elementos estaran sin definir. Cuidado no eliminar asi elementos.
    Semi foreach en JS:
    for(var coche in coches){
    alert(coches(coche));
    }
  2. Inicialización de matrices y matrices multidimensionales.
    var coches = new Array(“1″,”2″,”AD”); var coches = [“1″,”2″,”AD”]; var distintos = [“cadena”, 5, true];
    Multidimencionales: var dim1 = [1,2,3,4,5]; var dim2 = [1,2,3,4,5]; var dim2D = [dim1,dim2]; alert(dim2D[0][0]);
    Matrices escalonadas son las que contienen dentro matrices de diferentes dimenciones.
  3. Generar un alfabeto.
    Parseamos a numero: parseInt(“algo”);
    Comprobar si no es numero: if(isNaN(variable));
    Pide inputbox al usuario: prompt(“Pon numero”, “Valor defecto 26”);
    Cuando mostramos por pantalla matrices como string, separa valores con comas.
  4. Matrices asociativas: no los implemente realmente este tipo de matrices. Realmente es definicion de propiedades
    coches[“Alemanes”] = [“Audi”, “Volkswagen”, “Porsche”];
    alert(coches[“Alemanes”]) o por acceso a propiedad alert(coches.Alemanes);
  5. Manipulación de elementos de matrices.
    Unir en string usando elemento: var mEjemplo = [0,1,2,3,4,5]; mEjemplo.join(“–“); // Por defecto comas.
    Unir matrices: var mat1 = [1,2,3]; var mat2 = [“A”,”B”,”C”,”D”]; var nuevaMatriz = mat1.concat(mat2);
    Subconjunto de matrices (extracción): var subConjunto = sourceMatriz.slice(2,5); // Elementos del 2 al 5
    Matrices se pasan por referencia porque son objetos.
    Quitar elementos de matriz: matriz.splice(3,2) // Retira desde elemento 3, 2 elementos. Y resto de elementos se mueven para que no quedan huecos.
    Colas: var matriz = [1,2,3,4]; matriz.unshift(5,6) – meter al principio de cola; matriz.shift() – quita primer elemento.
    Pilas: var matriz = [1,2,3,4]; matriz.push(5) – meter en matriz; matriz.pop() – quita de matriz.
    Ordenacion:
    mat.reverse() (hace vuelta a elementos de matriz cambiando orden original de matriz);
    mat.slice().reverse() (copia matriz y invierte copia);
    mat.sort() (ordena la matriz como si fueran cadenas basando en valores unicode);
    Ordenacion especifica: var frutas = [“Naranjas”, “Pera”, “Melocoton”]; function ord(f1,f2){ return 0/1/2; frutas.sort(ord);
    Busquedas:
    mat.indexOf(“cadena buscada”) -> devuelve posición de primera ocurrencia de la cadena en la matriz.
    mat.indexOf(“cadena buscada”, 4) -> devuelve posición de primera ocurrencia de la cadena en la matriz despues de posición 4.
    lastIndexOf(“cadena buscada”) -> devuelve posición de ultima ocurrencia de la cadena en la matriz.
    Si se devuelve -1 -> no lo encuentra.
    Shims – funciones que sustituyen funciones si las primeras no existen.
    Procesamiento de elementos:
    Filtrar y extraer los que cumplen determinada condicion: var pares=mat.filter(esPar); function esPar(n){return n%2==0;}
    Indica si alguno cumple: mat.some(esPar);
    Indica si todos cumplen: mat.every(esPar);
    Aplica funcion a todos elementos en su retorno sin modificar matriz original: mat.map(elDoble); function elDoble(n){return n*2;}
    Map / Reduce para muchos datos.
    Aplicar funcion sin modificaciones: mat.forEach(mostrar); mostrar(n, indice, referenciaMatriz){alert(“Indice:”+indice+”,valor:”+n);

Detalles sobre JavaScript

Diferentes pequeños detalles de JavaScript que no se utilizan de forma muy habitual, pero que son bastante útiles.

  1. ScratchPatch (Firefox Shift+F4) – para escribir JS y ejecutar. Usa console.log(…) con consola (F12). Para poder hacer copy/paste escribir “permitir pegar” o “allow pasting” y CTRL+R.
    2.1. Operador ternario. Ej.: (n%2) == 0 ? alert(“numero par”) : alert(“numero impar”);
    2.2. Cortocircuito de expresiones lógicas. && o ||. Si primeras condiciones no se cumplen, resto no se verifican.
    2.3. Valores pseudo-Booleanos: Truly y Falsy (falsosos y verdosos). Ej.: if (window.Worker).
    Importante el orden: alert(“cualquier cosa” && true) -> true, alert( true && “cualquier cosa”); -> “cualquier cosa”. Operadores && y || devuelven valor de primer o segundo operando, no solo true/false. En && si primero es false, se devuelve primero, en || si primero es true se devuelve primer operando. Convertir algo en un booleano siempre con !!: !!”variable”. Se utiliza mucho en “return !!res;” en funciones.
  2. Uso avanzado de bucles determinados. Cambiar y complicar partes de los bucles. for (; i< 10; i++), for (var i = 0, j = 10; i< j; i++), for (var i = 0; ; i++), for (var i = 0, j = 0; i<10 && j < 5; i++, j++), for (;;)
  3. Uso de expresiones complejas con switch. Truco para tener condiciones complejas:
    switch (true) {
    case x > 0 && x < 10: alert(“x > 0 && x < 10”); break; case x > 0 && x < 20: alert(“x > 0 && x < 20”); break; case x < 0 || x > 100:
    alert(“x < 0 || x > 10”);
    break;
    default:
    alert(“Ninguno”);
    }
    5.1. Ámbito de las variables. Global desde cualquier parte de codigo (se define fuera de función). Local – solo dentro de una función.
    5.2. Shadowing u ocultamiento de variables. Cuando funcion tiene variable con mismo nombre en distinto ambito, prevalece la de ambito menor.
    5.3. Hoisting o elevación. Hay diferencia entre variable no definida y la que no existe. Si se define mas tarde, javascript lo mueve por dentro al principio de la función.
    5.4. Sobrecarga de funciones. Podemos tener mas argumentos de los definidos. Ej.:
    funcion sumarNumeros(){
    var parcial = 0;
    for (var i=0;i, <, etc.). Comparación teniendo en cuenta lenguaje indicado con “localeCompare”. Por defecto usa lenguaje de navegador.