Proprietà private in NodeJS

P

Proprietà private in NodeJS

Una proprietà privata è una proprietà accessibile solo alle funzioni membro di istanze della stessa classe. A differenza di altri linguaggi, JavaScript non dispone di supporto nativo per proprietà private. Col tempo le persone hanno trovato vari modi per emulare proprietà private utilizzando le funzioni linguistiche esistenti e le due tecniche comuni sono i prefissi e gli closures.

Entrambi gli approcci hanno inconvenienti, sono rispettivamente non restrittivi o troppo restrittivi. Una migliore alternativa è quella di utilizzare oggetti WeakMap che risolvono entrambi questi problemi. Anche qui mostrato è come generalizzare l’idea di utilizzare WeakMaps, associando una o più proprietà private ad un oggetto, associando uno o più namespaces a ciascun oggetto. Uno namespace è semplicemente un oggetto su cui si definiscono una o più proprietà private.

 

Usando i Prefissi

Una tecnica comune per implementare proprietà private è quella di prefiggere ogni nome di proprietà privata con un sottolineatura. Si consideri il seguente esempio:

function Punto(x, y) {
this._x = x;
this._y = y;
}

Le proprietà _x e _y sono destinate a essere private e consentono l’accesso solo alle funzioni dei membri.

Per dare permessi di lettura e scrittura a una proprietà privata da qualsiasi funzione, una cosa comune è definire le funzioni getter / setter della proprietà, rispettivamente:

Punto.prototype.getX = function () {
return this._x;
};

Punto.prototype.setX = function (x) {
this._x = x;
};

Punto.prototype.getY = function () {
return this._y;
};

Punto.prototype.setY = function (y) {
this._y = y;
};

La tecnica di cui sopra è semplice e esprime in modo chiara l’intenzione. Tuttavia, l’utilizzo di un prefisso di sottolineatura è solo una convenzione di codifica e non è attuato dalla lingua: non c’è nulla per impedire ad un utente di accedere direttamente a una proprietà che dovrebbe essere privata.

 

Usando i Closures

Un’altra tecnica comune è definire le proprietà private come variabili e le loro funzioni getter e setter come una closure su queste variabili:

function Punto(_x, _y) {
this.getX = function () {
return _x;
};

this.setX = function (x) {
_x = x;
};

this.getY = function () {
return _y;
};

this.setY = function (y) {
_y = y;
};
}

Questa tecnica richiede le funzioni membro che hanno bisogno di accedere a proprietà private da definire sull’oggetto stesso, anziché il suo prototipo. Ciò è leggermente meno efficace dell’utilizzo della convenzione di sottolineatura, ma non significativamente per la maggior parte delle applicazioni.

Il vantaggio di questa tecnica è che offre più protezione: non c’è modo per l’utente di accedere a una proprietà privata, ad eccezione dell’utilizzo della funzione getter o setter. Tuttavia, l’uso di closures rende le proprietà private troppo restrittive: poiché non vi è modo di accedere a variabili in una closure da un’altra closure, non c’è modo per gli oggetti della stessa classe di accedere alle proprietà private di ciascuno.

 

Da WeakMap a Namespace

Le tecniche sopra indicate non sono sufficientemente restrittive (prefissi) o troppo restrittive (closures), tuttavia la recente introduzione di WeakMaps fornisce una soluzione. WeakMaps sono state introdotte in JavaScript in ECMAScript 2015.

Usando i Weakmaps una soluzione migliore sarebbe quella di memorizzare tutte le proprietà private su un singolo oggetto, denominato spazio dei nomi, e quindi memorizzare lo spazio dei nomi come proprietà privata nell’oggetto originale. Utilizzando gli spazi dei nomi, l’esempio precedente può essere riscritto come segue:

let map = new WeakMap();

let internal = function (object) {
if (!map.has(object))
map.set(object, {});
return map.get(object);
}

function Punto(x, y) {
internal(this).x = x;
internal(this).y = y;
}

Punto.prototype.getX = function () {
return internal(this).x;
};

Punto.prototype.setX = function (x) {
internal(this).x = x;
};

Punto.prototype.getY = function () {
return internal(this).y;
};

Punto.prototype.setY = function () {
internal(this).y = y;
};

 

Usando le funzionalita’ di ES6 il pezzo di codice qui sopra puo’ essere scritto cosi:

class Punto {
constructor(x, y) {
internal(this).x = x;
internal(this).y = y;
}

getX() {
return internal(this).x;
}

setX(x) {
internal(this).x = x;
}

getY() {
return internal(this).y;
}

setY() {
internal(this).y = y;
}
}

L’unico modo per una funzione di accedere alle proprietà x e y è se ha un riferimento ad un’istanza di Point e del suo namespace interno. Mantenere lo snamespace nascosto da tutte le funzioni, tranne i membri di Punto, implementa efficacemente proprietà private. Inoltre, poiché i membri di Punto hanno un riferimento allo namespace interno, possono accedere alle proprietà private in altre istanze di Punto.

 

 

Conclusione

Spesso la nozione di proprietà private in Javascript e’che non esistono ma in questo articolo si e’ vista la tecnica del Weakmaps. Questa tecnica e’ molto efficacce e efiicciente per farsi che le proprietà private siano veramente private e solo accessibili all’interno della classe.

 

Scritta da: Ary Homebrew

A proposito di me

Andrew Raieta

Smanettone e appassionato di hardware fin da piccolo a 13 anni monta il suo primo PC, così iniziando ad esplorare quel mondo meraviglioso di linux ed essere sempre di più un utente attivo. Più avanti negli anni decide di iscriversi all’università così da intraprendere una laurea in computer science e nel frattempo dedicarsi allo studio del machine learning. Nell’ottobre del 2017 decide di scrivere sul blog per far scoprire il mondo di linux e condividere interessanti articoli tecnici sullo scripting.

Di Andrew Raieta

Gli articoli più letti

Articoli recenti

Commenti recenti