Recentemente ho sviluppato Angular Cloud Data Connector, che consente agli sviluppatori angolari di utilizzare i dati del cloud, in particolare i servizi mobili di Azure, utilizzando standard web come il DB indicizzato. Stavo cercando di creare un modo per gli sviluppatori JavaScript per incorporare membri privati in un oggetto.
La mia tecnica per questo caso specifico è usare quello che chiamo "spazio di chiusura". In questo tutorial, voglio condividere con te come utilizzare questo per i tuoi progetti e come influenza le prestazioni e la memoria per i principali browser.
Ma prima di immergerci, lascia che ti spieghi perché potresti aver bisogno di membri privati, oltre a un modo alternativo di "simulare" i membri privati.
Sentiti libero di darmi un ping su Twitter se vuoi discutere questo articolo: @deltakosh.
Quando si crea un oggetto utilizzando JavaScript, è possibile definire i membri del valore. Se si desidera controllare l'accesso in lettura / scrittura su di essi, sono necessari accessor che possono essere definiti in questo modo:
var entity = ; entity._property = "Ciao mondo"; Object.defineProperty (entità, "proprietà", get: function () return this._property;, set: function (value) this._property = value;, enumerable: true, configurable: true);
In questo modo, hai il pieno controllo sulle operazioni di lettura e scrittura. Il problema è che il _proprietà
membro è ancora accessibile e può essere modificato direttamente.
Questo è esattamente il motivo per cui è necessario un modo più efficace per definire membri privati a cui è possibile accedere solo tramite le funzioni dell'oggetto.
La soluzione è usare lo spazio di chiusura. Questo spazio di memoria è costruito per te dal browser ogni volta che una funzione interna ha accesso alle variabili dall'ambito di una funzione esterna. Questo può essere difficile a volte, ma per il nostro argomento questa è una soluzione perfetta.
Quindi modifichiamo il codice precedente per utilizzare questa funzione:
var createProperty = function (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (valore) currentValue = value;, enumerable: true, configurable : vero ); var entity = ; var myVar = "Ciao mondo"; createProperty (entità, "proprietà", myVar);
In questo esempio, il createProperty
la funzione ha a valore corrente
la variabile che può ottenere e impostare le funzioni può vedere. Questa variabile verrà salvata nello spazio di chiusura delle funzioni get e set. Solo queste due funzioni ora possono vedere e aggiornare il valore corrente
variabile! Missione compiuta!
L'unica avvertenza che abbiamo qui è che il valore di origine (myVar
) è ancora accessibile. Quindi ecco che arriva un'altra versione per una protezione ancora più robusta:
var createProperty = function (obj, prop) var currentValue = obj [prop]; Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (value) currentValue = value;, enumerable: true, configurable: true); var entity = property: "hello world"; createProperty (entità, "proprietà");
Usando questo metodo, anche il valore sorgente viene distrutto. Quindi missione pienamente compiuta!
Diamo ora un'occhiata alle prestazioni.
Ovviamente, gli spazi di chiusura o anche le proprietà sono più lenti e più costosi di una semplice variabile. Ecco perché questo articolo si concentra maggiormente sulla differenza tra il modo regolare e la tecnica dello spazio di chiusura.
Per confermare l'approccio dello spazio di chiusura non è troppo costoso rispetto al modo standard, ho scritto questo piccolo punto di riferimento:
Informatica ...
Creo 1 milione di oggetti, tutti con un membro di proprietà. Quindi faccio tre test:
Ecco una tabella e una tabella dei risultati:
Possiamo vedere che la versione dello spazio di chiusura è sempre più veloce rispetto alla versione normale e dipende dal browser, può essere un'ottimizzazione davvero impressionante.
Le prestazioni di Chrome sono meno di quanto mi aspettassi. Potrebbe esserci un bug, per sicurezza, ho contattato il team di Google per capire cosa sta succedendo qui. Inoltre, se vuoi testare come funziona in Microsoft Edge, il nuovo browser Microsoft che verrà fornito con Windows 10, puoi scaricarlo qui.
Tuttavia, se osserviamo da vicino, possiamo scoprire che l'utilizzo dello spazio di chiusura o persino di una proprietà può essere dieci volte più lento dell'accesso diretto a un membro. Quindi avvisati e usalo saggiamente.
Dobbiamo anche verificare che questa tecnica non consumi troppa memoria. Per confrontare la memoria ho scritto questi tre piccoli pezzi di codice:
var sampleSize = 1000000; var entities = []; // Creazione di entità per (var index = 0; index < sampleSize; index++) entities.push( property: "hello world (" + index + ")" );
var sampleSize = 1000000; var entities = []; // Aggiunta di proprietà e utilizzo di un membro locale per il salvataggio di valori privati per (indice var = 0; indice < sampleSize; index++) var entity = ; entity._property = "hello world (" + index + ")"; Object.defineProperty(entity, "property", get: function () return this._property; , set: function (value) this._property = value; , enumerable: true, configurable: true ); entities.push(entity);
var sampleSize = 1000000; var entities = []; var createProperty = function (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (valore) currentValue = value;, enumerable: true, configurable : vero ); // Aggiunta di proprietà e utilizzo dello spazio di chiusura per il salvataggio di valori privati per (indice var = 0; indice < sampleSize; index++) var entity = ; var currentValue = "hello world (" + index + ")"; createProperty(entity, "property", currentValue); entities.push(entity);
Poi ho eseguito tutti questi tre codici e lanciato il profilo di memoria incorporato (esempio qui con gli strumenti F12):
Ecco i risultati che ho ottenuto sul mio computer:
Tra lo spazio di chiusura e il modo normale, solo Chrome ha risultati leggermente migliori per la versione dello spazio di chiusura. IE11 e Firefox usano un po 'più di memoria, ma i browser sono relativamente comparabili - gli utenti probabilmente non noteranno differenze tra i browser moderni.
Potrebbe sorprendervi un po ', ma Microsoft ha un sacco di apprendimento gratuito su molti argomenti JavaScript open source, e siamo in missione per creare molto di più con Microsoft Edge in arrivo. Controlla il mio:
Oppure le serie di apprendimento del nostro team:
E alcuni strumenti gratuiti: Visual Studio Community, Azure Trial e strumenti di test cross-browser per Mac, Linux o Windows.
Come puoi vedere, le proprietà dello spazio di chiusura possono essere a ottimo modo per creare dati davvero privati. Potrebbe essere necessario affrontare un piccolo aumento del consumo di memoria, ma dal mio punto di vista questo è abbastanza ragionevole (e a quel prezzo si può avere un grande miglioramento delle prestazioni rispetto all'uso regolare).
E comunque se vuoi provarlo da solo, ti preghiamo di trovare tutto il codice usato qui. Qui c'è un buon "how-to" su Azure Mobile Services.
Questo articolo fa parte della serie di web dev tech di Microsoft. Siamo entusiasti di condividere Microsoft Edge e il nuovo Motore di rendering EdgeHTML con te. Ottieni macchine virtuali gratuite o test in remoto sul tuo dispositivo Mac, iOS, Android o Windows @ http://dev.modern.ie/.
Scopri JavaScript: la guida completa
Abbiamo creato una guida completa per aiutarti a imparare JavaScript, sia che tu stia appena iniziando come sviluppatore web o che desideri esplorare argomenti più avanzati.