Imparare JavaScript dall'astratto al concreto: il DOM

Imparare JavaScript dall'astratto al concreto: il DOM

JavaScript non andrebbe mai studiato come linguaggio astratto ma nelle sue applicazioni pratiche sui documenti Web. Questo perché JavaScript nasce come linguaggio per interagire con pagine HTML ed aggiungere un certo livello di dinamismo a tali pagine. Se si studia JavaScript prescindendo dai documenti Web si corre il rischio di padroneggiare solo una parte del linguaggio.

Concetti astratti

I concetti astratti del linguaggio comprendono:

  1. Tipi di dati.
  2. Oggetti.
  3. Funzioni.

In JavaScript i tipi di dati fondamentali (stringhe, numeri, ecc.) sono anche oggetti in quanto questo linguaggio è basato sugli oggetti. Come si vedrà, a loro volta anche le funzioni sono oggetti. Quando si programma in JavaScript si manipolano questi dati. Per manipolazione si intende quel processo che a partire dai dati iniziali produrrà un risultato finale.

Ad esempio se ho una stringa di cinque caratteri potrei voler estrarre solo il primo carattere. La cosa da capire ora è che non esiste mai un solo modo per ottenere un risultato. Posso ad esempio scrivere:


var str = 'Hello';
var firstChar = str.charAt(0); // 'H'

oppure:


var str = 'Hello';
var firstChar = str[0] // 'H'

La domanda che tutti si pongono a questo punto è: quale metodo è il migliore? In realtà questa domanda andrebbe riformulata come: qual'è il modo più semplice ed efficiente per ottenere un determinato risultato?. Nel nostro caso è indubbiamente il secondo ma attenzione: solo nel caso specifico di cui sopra questo metodo risponde in pieno alla nostra domanda. Infatti quando cambiano le condizioni da soddisfare per ottenere un determinato risultato cambierà di conseguenza anche il metodo adottato. In altre parole non esistono soluzioni definitive e dalla validità assoluta.

In JavaScript inoltre non esistono classi, ma solo oggetti. Il paradosso di questo linguaggio è che la tradizionale distinzione tra classe e oggetto intesa come relazione tra modello e istanza viene mantenuta pur non essendoci una implementazione della parola chiave class (almeno fino ai più recenti sviluppi dello standard ECMAScript). Nell'esempio precedente str è un'istanza dell'oggetto base String. Avremmo anche potuto scrivere:


var str = new String('Hello');

L'operatore new, come dice il significato del suo nome, crea una nuova istanza dell'oggetto String. Gli oggetti non sono altro che collezioni di coppie proprietà/valore raccolte insieme sotto il nome comune dell'oggetto. Quando una proprietà è una funzione, come nel caso di String.charAt(), si chiama metodo. La forza di JavaScript sta soprattutto nel fatto che possiamo definire i nostri oggetti personalizzati:


function Person(name) {
	this.name = name; // this si riferisce a Person
	
	this.sayName = function() {
		alert(this.name);
	}
}

var Gabriele = new Person('Gabriele'); // ora Gabriele.name = 'Gabriele'
Gabriele.sayName(); // 'Gabriele'

Person è il nostro modello originario. Al suo interno la parola chiave this fa riferimento all'oggetto corrente. Quando la funzione viene chiamata con l'operatore new, la proprietà name assume il valore del parametro passato alla funzione, in questo caso la stringa Gabriele. A quel punto il metodo sayName() può visualizzare il valore corrente della proprietà name.

Come si può capire dall'esempio precedente, le funzioni in JavaScript possono essere usate come costruttori di oggetti o come metodi di un oggetto. Ma il compito principale delle funzioni è quello di operare sui dati. Possiamo usare le funzioni per generalizzare delle operazioni sui dati. Ad esempio:


var ucFirst = function(str) {
	var output = '';
	var firstChar = str[0];
	var strPart = str.substring(1, str.length);
	var upper = firstChar.toUpperCase();
	output = upper + strPart;
	return output;
};

La funzione ucFirst() accetta come argomento una stringa (str). Di questa stringa vengono isolati il primo carattere ed il resto della stringa. Il primo carattere viene messo in maiuscolo e viene restituita (return) una nuova stringa (output) che avrà il primo carattere in maiuscolo.

Questa funzione può essere riutilizzata in modo generico. Altre volte invece le funzioni sono più specifiche e si limitano ad operare delle routine. Ad esempio:


var preloadImages = function() {
	var images = ['1.jpg', '2.jpg', '3.jpg'],
		len = images.length,
		i;
	for(i = 0; i < len; i++) {
		var src = images[i];
		var img = new Image();
		img.src = src;
	
	}

};

window.onload = function() {
	preloadImages();
}

Questa funzione si limita ad eseguire il preload delle immagini. Non ha un valore da restituire e quindi l'interprete JavaScript gli assegnerà il valore undefined come valore di ritorno. Come si può notare, questa funzione esegue una routine ed in genere funzioni come questa sono molto usate in JavaScript.

Dall'astratto al concreto: il DOM

I concetti astratti che abbiamo visto trovano ampia applicazione nel DOM (Document Object Model, Modello ad Oggetti del Documento). In questo modello un frammento HTML come il seguente:


<div id="container">
	<p>Test</p>
</div>

è composto da due oggetti elemento (HTMLElement), ossia <div id="container"> e <p>. Il paragrafo a sua volta contiene un nodo figlio di tipo testo (#text), ossia Test, mentre il suo genitore, oltre al paragrafo, contiene anche un nodo attributo (#attr) ossia l'ID container.

Tutti i concetti che abbiamo visto sui metodi e le proprietà degli oggetti JavaScript si applicano anche agli oggetti del DOM. Per esempio, per reperire l'ID del contenitore possiamo sia usare una proprietà:


var container = document.getElementById('container');
var containerID = container.id; // 'container'

che un metodo:


var container = document.getElementById('container');
var containerID = container.getAttribute('id'); // 'container'

Possiamo anche utilizzare concretamente ciò che abbiamo appreso sulle funzioni:


var container = document.getElementById('container');
var containerID = container.id; // 'container'
container.id = ucFirst(containerID); // ora id = 'Container'

In definitiva, è sul DOM che si riversa la maggior parte dei concetti astratti appresi nello studio di JavaScript. Grazie al DOM noi possiamo interagire pienamente con i documenti Web e modificarne la struttura ed il comportamento secondo quelli che sono i nostri scopi.

Torna su