Skip to content

Latest commit

 

History

History
715 lines (500 loc) · 21.9 KB

File metadata and controls

715 lines (500 loc) · 21.9 KB

OBJETOS


1. Introducción

En este apartado profundizamos en el trabajo con objetos.

  • Es aconsejable inicializar los objetos cuando se crean.
  • El constructor hace esta tarea, pero en Javascript es preferible hacerlo sin usar el constructor.
// formas permitidas, pero no recomendadas, excepto para Date()

let a = new Number();    // objeto de clase Number. A evitar. Debe usarse el tipo primitivo.
let b = new Boolean();   // objeto de clase Boolean. A evitar. Debe usarse el tipo primitivo.
let c = new String();    // objeto de clase String. A evitar. Debe usarse el tipo primitivo.
let d = new Array();     // objeto de clase Array. A evitar. Debe usarse el tipo primitivo.
let e = new Date();      // objeto de clase Date.
let f = new RegExp();    // objeto de clase RegExp. A evitar.
let g = new Function();  // getElementbyclass objeto de clase Function. A evitar.
let h = new Object();    // objeto de clase Object genérico. A evitar.
// formas recomendadas

let a = 0;               // número primitivo
let b = false;           // booleano primitivo
let c = "";              // texto primitivo
let d = [];              // objeto array  
let f = /()/;            // objeto regexp
let g = function(){};    // objeto function
let h = {};              // objeto object

1.1. Date

Para trabajar con fechas debemos crear un objeto de la clase Date.

Una forma de llamar al constructor es:

let fecha = new Date(año, mes, día, hora, minutos, segundos, milisegundos)

IMPORTANTE: Los meses se numeran empezando en 0. Enero es el mes 0, Febrero el 1, ...

// Ejemplos

let f1 = new Date(2017, 00, 01, 22, 30, 00, 999);  // 1 Enero de 2017, 22:30:00.999
let f2 = new Date(2017, 00, 01, 22, 30, 00);       // 1 Enero de 2017, 22:30:00
let f3 = new Date(2017, 00, 01, 22, 30);           // 1 Enero de 2017, 22:30:00
let f4 = new Date(2017, 00, 01);                   // 1 Enero de 2017, 00:00:00
let f5 = new Date();                               // Fecha y hora actual

Otra forma de llamar al constructor es:

let fecha = new Date("YYYY-MM-DDTHH:MI:SSZ");

NOTAS:

  • En este caso Enero sí empieza en 1.
  • La fecha y la hora se separan con una T mayúscula.
  • La hora UTC (Universal Time Coordinated) o GMT (Greenwich Mean Time) se define con una letra mayúscula Z.
  • Si se crea una fecha/hora en GMT, la fecha y la hora se convertirán a la hora local del usuario.
  • Para indicar otra zona horaria deberemos sustituir la letra Z por +HH:MI o -HH:MI
// Ejemplos

let f1 = new Date("2017-01-01T23:30:00");         // Hora local, tal cual  
let f2 = new Date("2017-01-01T23:30:00+01:00");   // Hora de España
let f3 = new Date("2017-01-01T23:30:00-05:00");   // Hora de Nueva York
let f4 = new Date("2017-01-01T23:30:00Z");        // Hora de Londres y Canarias, a nosotros nos aparecerá una hora más 

Conversión de Date a String

Suele ser habitual la conversión del tipo date al tipo string. Para ello podemos usar el método toISOString

let f1 = new Date()          // type object date
let s1 = f1.toISOString()    // type string

Extracción de fecha

Para obtener sólo la fecha, sin la hora, podemos hacer:

let f1 = new Date()          // type object date
let s1 = f1.toISOString()    // type string

let fecha = s1.split('T')[0] // type string 

Extracción de hora

Para obtener sólo la hora, sin la fecha, podemos hacer:

let f1 = new Date()          // type object date
let s1 = f1.toISOString()    // type string

// Todas la variables que aparecen a continuación son de tipo string

let hora = s1.split('T')[1] 
let horaSinZ = s1.split('T')[1].split('Z')[0]
let horaSinMS = s1.split('T')[1].split('.')[0]

1.2. RegExp (Expresiones Regulares)

Las expresiones regulares es un asunto de cierta complejidad. En las referencias tienes un desarrollo detallado. Una expresión regular no es más que un patrón de texto.

Las expresiones regulares tienen multiples utilidades. Una de las más frecuentes es la validación de datos respecto a un patrón determinado.

Los siguientes carácteres tienen un significado especial:

^    Indica el principio de una cadena
$    Indica el final de una cadena
()   Un agrupamiento de parte de una expresión
[]   Un conjunto de caracteres de la expresión
{}   Indica un número o intervalo de longitud de la expresión
.    Cualquier caracter salvo el salto de línea
?    0-1 ocurrencias de la expresión
+    1-n ocurrencias de la expresión
*    0-n ocurrencias de la expresión
\    Para escribir un caracter especial como los anteriores y que sea tratado como un literal
|    Para indicar una disyunción lógica (para elegir entre dos valores: a|b se tiene que cumplir al menos uno de los dos)

Ejemplo de validación de teléfono:

let telefono = /^[6789][0-9]{8}$/;

telefono.test ('123456789');  // false
telefono.test ( '95566622');  // false
telefono.test ('95566622a');  // false
telefono.test ('609123456');  // true

Ejemplo de validación de código postal:

let codigoPostal = /^[0-9]{4,5}$/;

codigoPostal.test ( '14500');  // true
codigoPostal.test (  '9500');  // true
codigoPostal.test ('A11450');  // false
codigoPostal.test (     '1');  // false

Ejemplo de validación de URLs:

let url = /^(http|ftp|https)\:\/\/[a-z0-9\_-]+(\.[a-z0-9\_-]+)*$/

url.test ('https://google.es');             // true
url.test ('ftp://ftp.rediris.es');          // true
url.test ('file:///bin/bash');              // false
url.test ('https://google.es/index.html');  // false

Ejemplo de validación de e-mail:

let email = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;

email.test ('jamj2000@gmail.com');            // true
email.test ('pepe_lopez@ventas.tienda.com');  // true
email.test ('pepe#lopez@tienda.com');         // false
email.test ('pepe_lopez@ventas/tienda.com');  // false

Ejemplo dentro de página web

<!DOCTYPE html>
<html lang="es">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Validación de Código Postal</title>
</head>
<body>
  <input id="cod" type="text" placeholder="Código Postal">
  <input id="val" type="button" value="Validar">
  <script>
       function validarCP(){
         return /^[0-9]{4,5}$/.test (document.getElementById('cod').value);          
       }
       
       document.getElementById('val').addEventListener('click', function () {
         if (validarCP()) alert('Código Postal CORRECTO')
         else             alert('Código Postal NO VÁLIDO');
       });
  </script>
</body>
</html>

REFERENCIAS:

1.2.1. Desestructuración

Se representa con { }, permite desempacar propiedades de objetos en distintas variables.

Se utiliza en numerosos ámbitos, para mayor información consultar el siguiente enlace:

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Ejemplo 1: Asignación de valores a variables desde un objeto origen

const user = {
    id: 42,
    is_verified: true
};

const {id, is_verified} = user;

console.log(id); // 42
console.log(is_verified); // true

Ejemplo 2: Desempacar campos de objetos pasados como parámetro de función

const usuario = {
  id: 42,
  nombre: 'jose',
};

function usuarioId({id}) {
  return id;
}

console.log(usuarioId(usuario)); // 42

1.2.2. Operador de expansión ...

También llamado spread operator y representado por 3 puntos ..., permite expandir (sacar del objeto) las propiedades.

Se utiliza en numerosos ámbitos, para mayor información consultar el siguiente enlace:

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Spread_syntax

Ejemplo 1: Copia superficial de un objeto

let obj1 = { nombre: 'jose', edad: 42 };
let objClonado = { ...obj1 };

console.log(objClonado); // { nombre: "jose", edad: 42 }

Ejemplo 2: Concatenación de propiedades

let obj1 = { nombre: 'jose', edad: 42 };
let obj2 = { nombre: 'juan', peso: 73 };

let obj3 = { ...obj1, ...obj2 };
console.log(obj3) // { nombre: "juan", edad: 42, peso: 73 }

1.3. Hacer copia de un objeto

Tenemos el siguiente objeto del que deseamos realizar una copia:

let persona = { nombre:"José",  edad:30,  direccion: {calle: "antigua", num: 1} };

NOTA: el código let copia = persona, no hace una copia.

Simplemente crea una referencia o "alias" llamado copia que apunta al mismo sitio que persona. Cualquier cambio en el objeto se ve reflejado en ambas variables.

let copia = persona;
persona.peso = 100;  // copia = {nombre: "José", edad: 30, peso: 100}

``

1.3.1. Copia superficial (Object.assign)

let persona = { nombre:"José",  edad:30,  direccion: {calle: "antigua", num: 1} };
let copia_superficial = {};

// shallow copy (copia superficial)
Object.assign(copia_superficial, persona);  

copia_superficial.nombre = "Juan";
persona.nombre;        // "José";

// No se copian los valores de los objetos internos. Sólo se copia su referencia. Por tanto:
copia_superficial.direccion.calle = "nueva";
persona.direccion.calle;         // "nueva" 

1.3.2. Copia superficial (Operador de expansión ...)

Existe una forma más moderna de realizar la copia superficial, y es usando el operador de expansion:

let persona = { nombre:"José",  edad:30,  direccion: {calle: "antigua", num: 1} };
let copia_superficial = { ...persona };    // shallow copy (copia superficial)

copia_superficial.nombre = "Juan";
persona.nombre;        // "José";

// No se copian los valores de los objetos internos. Sólo se copia su referencia. Por tanto:
copia_superficial.direccion.calle = "nueva";
persona.direccion.calle;         // "nueva" 

1.3.3. Copia profunda (JSON.parse y JSON.stringify)

Para un clonado profundo, necesitamos usar otra alternativa ya que Object.assign() copia valores de propiedades. Si el valor en la fuente es una referencia a un objeto, solo se copia la referencia en sí, como valor de la propiedad.

let persona = { nombre:"José",  edad:30,  direccion: {calle: "antigua", num: 1} };

// deep copy (copia profunda)
let copia_profunda = JSON.parse(JSON.stringify(persona));

// Se copian los valores de los objetos internos. Por tanto:
copia_profunda.direccion.calle = "ancha";
persona.direccion.calle;      // "antigua"; 

RESUMEN:

  • JSON.stringify() convierte un Objeto Javascript a String
  • JSON.parse() convierte un String a Objeto Javascript.

NOTA:

JSON es un formato de intercambio de datos que está estándarizado y que tiene las siguientes características:

  • Tanto las claves como los valores deben estar entre comillas dobles, no se permiten comillas simples.
  • Los valores de tipo number y de tipo boolean no llevan comillas
  • No se permite el uso de trailing commas (comas finales)
  • No se permite el uso de comentarios

Estas características a menudo son percibidas como limitaciones. Por ello existen formatos derivados de JSON con menores restricciones. Por ejemplo, VSCode usa archivos de configuración con extensión .json, pero el formato real es JSONC (JSON con Comentarios), que permite comentarios y comas finales.

Otro formato derivado de JSON es JSON5

Ni JSONC ni JSON5 están estándarizados.

1.3.4. Serialización

Aprovechamos la ocasión de haber visto previamente las funciones JSON.stringify() y JSON.parse() para hablar de la serialización.

¿QUÉ SE ENTIENDE POR SERIALIAR?

Simplificando mucho, podemos decir que serializar es pasar unos datos "paralelos" o compuestos a datos "serie" o simples. Por ejemplo, pasar un objeto a un string. Un string se considera un dato serie puesto que está compuesto por una serie de caracteres uno tras otro.

CÓMO Y CUÁNDO SERIALIZAR

const string = await JSON.stringfy(objeto)

La serialización es necesaria en los siguientes escenarios:

  • Al enviar información por la red
  • Al guardar información en un archivo

CÓMO Y CUÁNDO DESERIALIZAR

const objeto = await JSON.parse(string)

La deserialización es necesaria en los siguientes escenarios:

  • Al recibir información de la red
  • Al leer información en un archivo

1.3.5. Copia profunda (structuredClone)

Existe una forma más moderna de realizar la copia profunda, y es usando la función structuredClone:

let persona = { nombre:"José",  edad:30,  direccion: {calle: "antigua", num: 1} };

// deep copy (copia profunda)
let copia_profunda = structuredClone(persona);

// Se copian los valores de los objetos internos. Por tanto:
copia_profunda.direccion.calle = "ancha";
persona.direccion.calle;      // "antigua"; 

1.4. Propiedades y métodos

Los objetos tienen propiedades y métodos.

let persona = {
  nombre: "José",  // Propiedad
  edad: 30,        // Propiedad
  altura: 1.70,    // Propiedad
  peso: 100,       // Propiedad
  imc: function() { return this.peso / (this.altura*this.altura) }  // Método   
}

// Tanto propiedades como métodos pueden añadirse después de haberse definido el objeto

// Otro método
persona.saluda = function (saludo) {
  console.log (saludo + ', me llamo ' + this.nombre);
}

persona.imc();                  // 34.60
persona.saluda('Buenos días');  // Buenos días, me llamo José

1.5. Definir nuevas "clases"

1.5.1. Utilizando prototipos

El lenguaje Javascript es un lenguaje basado en prototipos, donde no hay clases explícitas y los objetos heredan directamente de otros objetos. Ésta es su forma de implementar la Programación Orientada a Objetos.

En los lenguajes basados ​​en clases, normalmente se crea una clase en tiempo de compilación y luego se instancian las instancias de la clase, ya sea en tiempo de compilación o en tiempo de ejecución. No puede cambiar el número o el tipo de propiedades de una clase después de definir la clase. Sin embargo, en JavaScript, puede agregar o eliminar propiedades de cualquier objeto en tiempo de ejecución. Si agrega una propiedad a un objeto que se utiliza como prototipo para un conjunto de objetos, los objetos para los que es el prototipo también obtienen la nueva propiedad.

// Función constructura del prototipo
function Persona (nombre, altura, peso) {
  this.nombre = nombre;
  this.altura = altura;
  this.peso   = peso;
  this.imc    = function () { return this.peso / (this.altura*this.altura) };
} 

let pepe = new Persona ('José', 1.70, 100);
let juan = new Persona ('Juan', 1.60, 90);
pepe.imc();


// Añadimos una propiedad al prototipo
Persona.prototype.mortal = true; 

// Añadimos un método al prototipo
Persona.prototype.saluda = function (saludo) {
  console.log (saludo + ', me llamo ' + this.nombre);
}

juan.saluda ('Hola');
pepe.saluda ('Buenos días');

1.5.2. Utilizando la palabra clave class

Sólo disponible a partir de ES6. Es azúcar sintáctico, puesto que en el fondo Javascript sigue siendo un lenguaje basado en prototipos.

class Persona {

  constructor (nombre, altura, peso) {
    this.nombre = nombre;
    this.altura = altura;
    this.peso   = peso;
    this.mortal = true;
  }
  
  // No hay coma de separación
  
  imc () {          // Método. Observa que no hay palabra function
    return this.peso / (this.altura*this.altura);
  }

  // No hay coma de separación

  saluda (saludo) { // Método. Observa que no hay palabra function
    console.log (saludo + ', me llamo ' + this.nombre);
  }

} // Fin de clase

let pepe = new Persona ('José', 1.70, 100);

REFERENCIAS:

1.6. Objetos predefinidos

1.6.1. Objeto window

Cuando trabajamos con el navegador web, el principal objeto es window, el cual posee innumerables propiedades y métodos.

Tres métodos interesantes son los que nos proporcionan cajas de diálogo:

  • alert
  • confirm
  • prompt
window.alert   ('Mensaje de bienvenida');
window.confirm ('¿De verdad deseas hacer eso?');
window.prompt  ('Escribe tu nombre y apellidos: ');

La cajas de diálogo confirm y prompt devuelven un valor. Por tanto, suele recogerse dicho valor y evaluarlo o tratarlo de alguna forma. Ejemplos:

if ( window.confirm ('¿De verdad deseas hacer eso?') )
  window.console.log ('Bien, tú lo has querido');
  
window.console.log ('Has dicho que te llamas ', window.prompt ('Escribe tu nombre y apellidos: '));

Tres propiedades interesantes (que a su vez son objetos) son:

  • navigator
  • document
  • console

Estos objetos los vemos en los siguientes apartados. Tiene a su vez sus propias propiedades y métodos. Ejemplo de propiedades para estos objetos son:

window.navigator.appVersion
window.document.title

NOTA: Todos estas propiedades y métodos pueden escribirse sin el prefijo window.

Por ejemplo, suele escribirse alert ('Hola') en lugar de window.alert ('Hola')

y document en lugar de window.document

1.6.2. Objeto navigator

Nos permite acceder a las propiedades y métodos del navegador web.

navigator.geolocation
         .getCurrentPosition( position => { 
             console.log ( position.coords.latitude + ', ' + position.coords.longitude ) 
          });
// Igual al anterior, guardado en una función y comprobando previamente el soporte del navegador

// Definición de función
function getLocation() {
    if ("geolocation" in navigator)  // if (navigator.geolocation) 
      return navigator.geolocation
                      .getCurrentPosition( position => { 
                          console.log ( position.coords.latitude + ', ' + position.coords.longitude ) 
                       });
    else
      return "Geolocation is not supported by this browser.";
}

// Llamada a la función
getLocation();

1.6.3. Objeto document

A través de este objeto accedemos al DOM (Document Object Model), el cual es un modelo del documento actual. De esta manera podemos acceder a cualquier elemento del documento y modificar su contenido.

Métodos interesantes son:

  • createElement
  • remove
  • appendChild
  • getElementById
  • getElementsByClassName
  • querySelector
  • getAttribute
  • setAttribute

Propiedades interesantes son:

  • textContent
  • innerHTML
  • value ( utilizado para inputs )

Ejemplo

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>DOM</title>
</head>
<body>
  <ul    id="lista"> </ul>
  <input id="boton" type="button" value="Pulsame">

  <script>
let list = document.getElementById('lista');

document.getElementById('boton').addEventListener ('click', function(){
  for (let i = 1; i <= 5; i++) {
    let item = document.createElement('li');
    item.appendChild(document.createTextNode('Item ' + i));

    item.onclick = function(ev) {
      console.log('Item ' + i + ' ha sido pulsado.');
    };
    list.appendChild(item);
  } 
});

  </script>
</body>
</html>

1.6.4. Objeto console

Se utiliza para mostrar mensajes por consola.

let agenda = [
  { nombre: 'José',  telefono: 300300300 },
  { nombre: 'Eva',   telefono: 200200200 },
  { nombre: 'Ana',   telefono: 100100100 },
  { nombre: 'Juana', telefono: 111222333 }
];

console.clear  ();                           // Limpia la consola
console.log    ('Mensaje de log');           // Muestra mensaje de log
console.info   ('Mensaje de información');   // Muestra mensaje de información
console.warn   ('Mensaje de aviso');         // Muestra mensaje de aviso
console.error  ('Mensaje de error');         // Muestra mensaje de error
console.debug  ('Mensaje de depuración');    // Muestra mensaje de depuración
console.table  (agenda);                     // Muestra en forma de tabla. Para navegador y nodejs
console.time   ('id')                        // Inicia temporizador  
console.timeEnd('id')                        // Muestra tiempo transcurrido desde console.time('id')

NOTA: En NodeJS, el objeto console existe por si mismo, es decir, en NodeJS no podemos escribir window.console.