Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 52 di 112
  • livello avanzato
Indice lezioni

Moduli

ECMAScript 2015 ha introdotto il supporto nativo dei moduli nello sviluppo di applicazioni Javascript. Ecco in cosa consiste.
ECMAScript 2015 ha introdotto il supporto nativo dei moduli nello sviluppo di applicazioni Javascript. Ecco in cosa consiste.
Link copiato negli appunti

Tra le novità introdotte dalle specifiche ECMAScript 2015 che hanno un impatto significativo nello sviluppo con JavaScript è da sottolineare senza dubbio il supporto nativo dei moduli. La definizione dei moduli proposta dallo standard evita il ricorso a soluzioni ad hoc e alla implementazione del Module Pattern, offrendo un meccanismo comune per tutti gli sviluppatori.

Secondo le specifiche, un modulo JavaScript è memorizzato in un file: esiste esattamente un modulo per file e un file contiene un solo modulo. In altre parole, per creare un modulo è sufficiente scrivere del codice JavaScript in un file ed esportare uno o più delle funzionalità implementate.

Il seguente è un esempio di modulo che esporta la funzione somma():

export function somma(x, y) {
	return x + y;
}

Come possiamo vedere, utilizziamo la parola chiave export per indicare che abbiamo intenzione di esportare la funzione somma(), cioè la rendiamo accessibile all'esterno del modulo. Tutto ciò che non viene esplicitamente esportato non sarà visibile fuori dal modulo:

function prodotto(x, y) {
	return x*y;
} 
export function somma(x, y) {
	return x + y;
}

Nell'esempio precedente esportiamo la funzione somma() ma non la funzione prodotto().

Oltre a funzioni possiamo esportare anche altri elementi definiti nel modulo, come ad esempio classi o costanti, come evidenziamo nel seguente esempio:

function prodotto(x, y) {
	return x*y;
} 
export function somma(x, y) {
	return x + y;
} 
export const pigreco = 3.141592;
export class Circonferenza {
	constructor(raggio) {
		this.raggio = raggio;
	}
}

Il modulo dell'esempio esporta, oltra alla funzione somma(), la costante pigreco e la classe Circonferenza.

Negli esempi visti finora abbiamo esportato ciascun elemento singolarmente premettendo davanti alla sua definizione la parola chiave export. È possibile esportare più elementi raggruppandoli come mostrato di seguito:

function prodotto(x, y) {
	return x * y;
} 
function somma(x, y) {
	return x + y;
} 
const pigreco = 3.141592; 
class Circonferenza {
	constructor(raggio) {
		this.raggio = raggio;
	}
} 
export {somma, pigreco, Circonferenza};

Import, alias e wildcard

Le funzionalità e gli altri elementi esportati da un modulo JavaScript possono essere importate da un altro modulo tramite la parola chiave import. Supponendo di aver salvato in un file mioModulo.js il codice visto negli esempi precedenti, il seguente è un esempio di importazione della funzione somma() all'interno di un altro modulo:

import {somma} from "mioModulo"; 
console.log(somma(2, 5));

Abbiamo specificato tra parentesi graffe l'elemento che abbiamo importato dal modulo mioModulo. Se non si specifica l'estensione del file che rappresenta il modulo è sottintesa l'estensione .js. L'elemento importato viene aggiunto allo scope corrente ed è accessibile come se fosse stato definito nel modulo corrente.

Per importare più elementi da un modulo è sufficiente indicare l'elenco all'interno delle parentesi graffe:

import {somma, pigreco} from "mioModulo";

È possibile specificare un alias per un elemento importato da un modulo, come mostrato di seguito:

import {somma, pigreco as pigrecopiupreciso} from "mioModulo"; 
var pigreco = 3.14;

In questo caso abbiamo importato la costante pigreco specificando l'alias pigrecopiupreciso, in modo da evitare un conflitto con la variabile pigreco locale al modulo corrente.

I motivi per utilizzare un alias possono essere diversi: oltre ad evitare conflitti con elementi presenti nel modulo corrente o importati da altri moduli, un alias può essere definito semplicemente per comodità, ad esempio per semplificare il nome o renderlo compatibile con una naming convention adottata in una specifica applicazione.

Se vogliamo importare tutti gli elementi esportati da un modulo possiamo specificare il simbolo * come nel seguente esempio:

import * as Matematica from "mioModulo"; 
console.log(Matematica.somma(2, 5));

In questo caso dobbiamo specificare un alias per identificare il contenuto del modulo ed utilizzare i singoli elementi messi a disposizione dal modulo importato tramite la dot notation, come possiamo dedurre dall'utilizzo della funzione somma() nell'esempio precedente.

default export

Gli esempi di esportazione visti finora sono noti come named export, cioè esportazioni di elementi puntuali definiti all'interno di un modulo. Abbiamo visto come sia possibile esportare uno o più elementi specificando per ciascuno la parola chiave export o esportando un gruppo di elementi con un'unica istruzione.

Oltre a questo tipo di esportazione, è possibile definire una esportazione di default (default export) all'interno di un modulo. Con questa modalità definiamo l'elemento rappresentativo del modulo, quello che viene esportato di default se non diversamente specificato. Ad esempio, riprendendo il codice visto prima, possiamo definire la funzione somma() come l'elemento di default del nostro modulo:

function prodotto(x, y) {
 	return x*y;
} 
export default function (x, y) {
 	return x + y;
} 
const pigreco = 3.141592; 
class Circonferenza {
 	constructor(raggio) {
 		this.raggio = raggio;
 	}
} 
export {pigreco, Circonferenza};

L'istruzione di esportazione in fondo al modulo non contiene più la funzione somma() dal momento che l'abbiamo definita come elemento per l'esportazione di default tramite export default. Naturalmente è possibile esportare un solo elemento come elemento di default.

Un elemento esportato di default viene importato in un altro modulo con la seguente sintassi:

import somma from "mioModulo";

Possiamo notare come, in questo caso, abbiamo specificato l'elemento da importare senza indicare le parentesi graffe. Inoltre nell'importazione di un elemento di default abbiamo la possibilità di specificare l'alias che ci fa più comodo contestualmente all'importazione. Infatti, la funzione esportata di default dal modulo mioModulo è una funzione anonima: abbiamo dato noi il nome di somma contestualmente all'importazione. Avremmo potuto effettuare l'importazione della funzione utilizzando il nome che ci faceva più comodo, come mostrato di seguito:

import addizione from "mioModulo";

Cose da ricordare nell'uso dei moduli

Prima di chiudere questo articolo sui moduli occorre evidenziare tre importanti segnalazioni:

  • l'importazione e l'esportazione di un modulo sono processi statici, cioè allo stato attuale non possiamo importare ed esportare un modulo a runtime in base alla valutazione di determinate condizioni (una proposta in tal senso è allo studio del comitato di standardizzazione)
  • l'importazione di un modulo è soggetta ad hoisting, cioè essa viene effettuata all'inizio della valutazione del codice contenuto in un modulo, indipendentemente dalla posizione dell'istruzione di import all'interno del modulo; per convenzione quindi si suggerisce di porre le istruzioni di import in cima ad modulo JavaScript
  • gli elementi importati da un modulo sono in sola lettura, cioè non possiamo assegnare un nuovo valore o ridefinire una funzione fuori dal suo scope di origine

Ti consigliamo anche