UT04 — Estructures definides per l'usuari en JavaScript¶
Introducció¶
Aquesta unitat introdueix les estructures de dades, amb especial atenció als arrays. S'explicarà l'objecte Array: creació, recorregut, eliminació d'elements i les propietats i mètodes disponibles. També es presentaran diferents tipus d'arrays (paral·lels i multidimensionals).
S'introdueixen les funcions: declaració, paràmetres, abast de variables, funcions niuades i funcions predefinides del llenguatge. Finalment, s'exposarà la creació d'objectes definits per l'usuari amb propietats i mètodes propis.
1. Arrays¶
Conceptes bàsics¶
En els llenguatges de programació existeixen estructures de dades que permeten emmagatzemar informació més complexa que una variable senzilla. L'array és una de les estructures més utilitzades: és una zona d'emmagatzematge contínua que pot contenir diversos valors en lloc d'un només, com succeeix amb una variable simple.
Els arrays també s'anomenen matrius o vectors. Des d'un punt de vista lògic, una matriu es pot concebre com un conjunt d'elements ordenats en fila (o files i columnes si té més dimensions).
Tots els arrays es consideren, essencialment, unidimensionals, però els seus elements poden ser al seu torn altres arrays, cosa que dóna lloc a arrays multidimensionals (fàcilment imaginables en una, dues o tres dimensions). És preferible no abusar de dimensions superiors si la lògica del programa no ho requereix, ja que això dificulta la lectura i mantenibilitat.
Els arrays són adequats quan l'accés a les dades és aleatori. Si predominen accessos seqüencials o la necessitat de canviar la grandària amb freqüència, una llista podria ser una opció més adequada.
Cada element d'un array és referenciat per la seva posició, anomenada índex. En JavaScript l'indexació és de base zero; per tant, el primer element té índex 0.
Els arrays apareixen en JavaScript des de la versió 1.1; per tant, en els navegadors actuals no hi ha limitacions per emprar-los.
Indexació (definició): procés d'organització ordenada de la informació per a obtenir resultats més ràpids i rellevants durant les cerques.
1.1 Treballant amb arrays¶
Un array és una estructura per emmagatzemar i manipular col·leccions de dades. A diferència d'altres llenguatges, en JavaScript els arrays són molt versàtils pel que fa al tipus de dades que poden contenir: cada posició pot tenir elements de tipus diferent.
En programació, un array es defineix com una col·lecció ordenada de dades; s'assembla a una taula o una fulla de càlcul. JavaScript utilitza internament arrays per gestionar col·leccions del document HTML (p. ex. anchors, forms, links, images). Exemple d'accés al primer enllaç: document.links[0].
Quan es dissenya una aplicació, cal identificar quan convé usar arrays. Per exemple, una sèrie de coordenades geogràfiques d'una ruta constitueix un bon candidat per a un array.
Creació¶
Per crear un array hi ha diverses sintaxis:
let coches = [ 'Seat', 'Audi', 'BMW', 'Toyota' ];
let numeros = [ 1, 5, 3, 9, 6, 4 ];
let diferentes = [ 'Pepe', 5, 'Juan', false ];
També es pot usar new Array() i assignar elements mitjançant índex:
let coches = new Array();
coches[0] = 'Seat';
coches[1] = 'Audi';
coches[2] = 'BMW';
coches[3] = 'Toyota';
És possible crear arrays associatius (associacions clau-valor):
let edades = new Array();
edades['Juan'] = 20;
edades['Ana'] = 18;
edades['Pedro'] = 25;
console.log(edades);
console.log(edades['Juan']);
console.log(edades['Ana']);
console.log(edades['Pedro']);
Recorregut¶
Per recórrer un array podem utilitzar els bucles coneguts. Per exemple:
let numeros = [ 1, 5, 3, 9, 6, 4 ];
for (let i = 0; i < numeros.length; i++) {
console.log(numeros[i]);
}
Altres constructes són:
for (let i in numeros) {
console.log(numeros[i]);
}
numeros.forEach(numero => console.log(numero));
I també es poden emprar map, reduce i filter:
let cuadrados = numeros.map(numero => { return numero * numero });
console.log(cuadrados);
Per saber-ne més
Per exemples detallats de map, filter i reduce:
https://code.tutsplus.com/es/tutorials/how-to-use-map-filter-reduce-in-javascript--cms-26209
Treballant amb elements¶
Afegir un element dinàmicament:
numeros[6] = 15;
console.log(numeros);
Si s'afegeix un element fora del final, les posicions intermèdies poden quedar amb valors indefinits.
Eliminar un element amb delete no redueix la longitud de l'array:
delete numeros[6];
console.log(numeros.length); // 7
console.log(numeros[6]); // undefined
Per reduir la mida cal usar splice (posició d'inici, nombre d'elements):
numeros.splice(5, 2);
console.log(numeros); // [ 1, 5, 3, 9, 6 ]
Propietats i mètodes¶
Propietats de l'objecte Array:
| Propietat | Descripció |
|---|---|
| constructor | Retorna la funció que va crear el prototype de l'array. |
length |
Ajusta o retorna el nombre d'elements d'un array. |
prototype |
Permet afegir propietats i mètodes a un objecte. |
Mètodes de l'objecte Array:
| Mètode | Descripció |
|---|---|
concat() |
Uneix dos o més arrays i retorna una còpia dels arrays units. |
join() |
Uneix tots els elements d'un array en una cadena. |
pop() |
Elimina l'últim element d'un array i el retorna. |
push() |
Afegeix nous elements al final d'un array i retorna la nova longitud. |
reverse() |
Inverteix l'ordre dels elements d'un array. |
shift() |
Elimina el primer element d'un array i el retorna. |
slice() |
Selecciona una part d'un array i retorna el nou array. |
sort() |
Ordena els elements d'un array. |
splice() |
Afegeix/elimina elements a un array. |
toString() |
Converteix un array a una cadena i retorna el resultat. |
unshift() |
Afegeix nous elements a l'inici d'un array i retorna la nova longitud. |
valueOf() |
Retorna el valor primitiu d'un array. |
Arrays paral·lels¶
Els arrays paral·lels són conjunts de dos o més arrays que comparteixen l'índex per referir-se a termes homologables. Exemple:
let personajes = [ 'Bob Esponja', 'Calamardo', 'Patricio' ];
let color = [ 'amarillo', 'beige', 'rosa' ];
for (let i = 0; i < personajes.length; i++) {
console.log(`${personajes[i]} es de color ${color[i]}`);
}
Arrays multidimensionals¶
Un element d'un array pot ser un altre array; això genera arrays multidimensionals. Exemple:
let personajes = [
[ 'Bob Esponja', 'amarillo'],
[ 'Calamardo', 'beige' ],
[ 'Patricio', 'rosa' ]
];
for (let i in personajes) {
console.log(`${personajes[i][0]} es de color ${personajes[i][1]}`);
}
2. Funcions¶
Conceptes bàsics sobre funcions¶
Una funció és la definició d'un conjunt d'accions preprogramades. Les funcions es poden invocar mitjançant esdeveniments o crides des del script.
És recomanable dissenyar funcions reutilitzables perquè esdevinguin blocs constructius que accelerin el desenvolupament.
Si bé altres llenguatges distingeixen mètodes i procediments, en JavaScript s'utilitza el terme funció per a tots dos casos. Una funció pot retornar un valor amb return, però no sempre és obligatori.
Sintaxi¶
Sintaxi tradicional:
function nombreFuncion ( [parametro1]....[parametroN] ) {
// instruccions
[return valor]
}
Sintaxi amb operador fletxa (arrow function), recomanada actualment:
const nombreFuncion = ([parametro1]...[parametroN]) => {
// instruccions
[return valor]
}
Els noms de funció segueixen les mateixes restriccions que les variables i haurien de reflectir l'acció que realitzen (p. ex. chequearCorreo, calcularFecha).
Per invocar una funció:
nombreFuncion(); // Executa les instruccions de la funció.
Si la funció retorna un valor i el volem capturar:
variable = nombreFuncion();
Les funcions en JavaScript són objectes i, per tant, poden tenir mètodes com toString() que retornen el seu codi font.
Paràmetres¶
Els paràmetres (arguments) permeten passar dades a una funció. En la definició, s'indiquen els noms de les variables que rebran els valors.
Exemple:
const saludar = (nombre) => {
alert(`Hola ${nombre}`);
}
saludar('Bob Esponja'); // Mostra alerta: "Hola Bob Esponja."
Els paràmetres són variables locals a la funció i s'inicialitzen quan s'invoca la funció.
Exemple d'una funció que retorna un valor:
const calcularMayor = (num1, num2) => {
return (num1 > num2) ? num1 : num2;
}
console.log(calcularMayor(7, 5)); // 7
Àmbit de les variables¶
Hi ha variables globals (definides fora de qualsevol funció) i variables locals (definides dins d'una funció).
Una variable global en JavaScript té abast dins del document actual carregat; totes les instruccions (incloses les de dins de funcions) poden accedir i modificar-la. Quan la pàgina es tanca, aquestes variables s'eliminen.
Una variable local es defineix dins d'una funció; el seu abast està limitat a la funció i no és accessible fora d'aquesta.
Reutilitzar el mateix nom per a una variable global i una local pot generar errors subtils (bugs) perquè la variable local oculta la global. S'aconsella evitar aquesta pràctica.
Exemple:
let nombre = 'Pepe';
const prueba = () => {
let nombre = 'Pedro';
console.log(nombre); // Pedro
}
console.log(nombre); // Pepe
prueba();
console.log(nombre); // Pepe
Funcions niuades¶
És possible declarar funcions dins d'altres funcions. Això permet encapsular funcionalitats que només tenen sentit dins del context de la funció principal i limitar l'abast (privadesa) d'aquestes funcions auxiliars.
Exemple:
const calcularHipotenusa = (cateto1, cateto2) => {
const calcularCuadrado = (x) => { return x * x; }
return Math.sqrt(calcularCuadrado(cateto1) + calcularCuadrado(cateto2));
}
console.log(calcularHipotenusa(1, 2)); // 2.23606797749979
Funcions predefinides (globals)¶
Les funcions globals són accessibles des de qualsevol lloc del codi i sovint permeten convertir tipus de dades o manipular cadenes i URLs. Alguns exemples:
| Funció | Descripció |
|---|---|
decodeURI() |
Decodifica caràcters especials d'una URL excepte: , / ? : @ & = + $ # |
decodeURIComponent() |
Decodifica tots els caràcters especials d'una URL. |
encodeURI() |
Codifica caràcters especials d'una URL excepte: , / ? : @ & = + $ # |
encodeURIComponent() |
Codifica tots els caràcters especials d'una URL. |
escape() |
Codifica caràcters especials en una cadena (excepte * @ - _ + . /). |
eval() |
Avalua una cadena i l'executa si conté codi. |
isFinite() |
Determina si un valor és un número finit vàlid. |
isNaN() |
Determina si un valor no és un número. |
Number() |
Converteix un valor a nombre. |
parseFloat() |
Converteix una cadena a nombre real. |
parseInt() |
Converteix una cadena a enter. |
unescape() |
Decodifica caràcters especials en una cadena (excepte * @ - _ + . /). |
3. Objectes¶
Conceptes bàsics sobre objectes¶
Un objecte en JavaScript és una col·lecció de propietats. Les propietats poden ser dades, tipus, funcions (mètodes) o altres objectes. Un mètode és, en essència, una funció associada a un objecte i té accés a les propietats d'aquest objecte: és una peça clau en la programació orientada a objectes.
Definició de classe¶
Per definir una classe (plantilla per crear objectes), s'utilitza la sintaxi:
class NombreClase {
// Cos de la classe
}
Per convenció, el nom de la classe comença amb majúscula.
Exemple inicial per a gestionar contactes:
class Contacto {
// Cos de la classe Contacto
}
Creació d'instàncies¶
Per crear un objecte a partir d'una classe s'utilitza l'operador new:
let pepe = new Contacto();
let juan = new Contacto();
Propietats¶
Les propietats representen l'estat d'un objecte. Es poden declarar en el cos de la classe o, preferentment, inicialitzar-les en el constructor utilitzant this.
Exemple:
class Contacto {
nombre;
correo;
}
let juan = new Contacto();
console.log(juan); // Object { nombre: undefined, correo: undefined }
juan.nombre = 'Juan';
console.log(juan.nombre); // Juan
Constructor¶
El constructor és una funció especial que s'executa en crear una instància amb new. Normalment s'usa per inicialitzar propietats.
class Contacto {
constructor(nombre, correo) {
this.nombre = nombre;
this.correo = correo;
}
}
let pepe = new Contacto('Pepe', 'pepe@gmail.com');
console.log(pepe); // Object { nombre: "Pepe", correo: "pepe@gmail.com" }
let juan = new Contacto();
console.log(juan); // Object { nombre: undefined, correo: undefined }
Mètodes¶
Els mètodes són funcions definides dins la classe que determinen el comportament dels objectes:
class Contacto {
nombre;
correo;
constructor(nombre, correo) {
this.nombre = nombre;
this.correo = correo;
}
saludar() {
return `Hola, soy ${this.nombre} y mi correo es ${this.correo}`;
}
}
let pepe = new Contacto('Pepe', 'pepe@gmail.com');
console.log(pepe.saludar()); // "Hola, soy Pepe y mi correo es pepe@gmail.com"
També hi ha mètodes estàtics, comuns a la classe i no a les instàncies, que es declaren amb la paraula clau static.
Herència¶
JavaScript permet crear jerarquies mitjançant extends. Una classe pot heretar estructura i comportament d'una altra:
class ContactoTelefonico extends Contacto {
telefono;
constructor(nombre, correo, telefono) {
super(nombre, correo);
this.telefono = telefono;
}
saludar() {
return `${super.saludar()} y mi teléfono es ${this.telefono}`;
}
}
let maria = new ContactoTelefonico('María', 'maria@gmail.com', '666112233');
console.log(maria.saludar()); // "Hola, soy María y mi correo es maria@gmail.com y mi teléfono es 666112233"
