Am dezvoltat recent un conector de date cloud, care permite dezvoltatorilor Angular să folosească date din cloud, în special Azure Mobile Services, utilizând standarde web ca DB indexate. Am încercat să creez un mod pentru dezvoltatorii JavaScript pentru a încorpora membri privați într-un obiect.
Tehnica mea pentru acest caz specific este de a folosi ceea ce eu numesc "spațiu de închidere". În acest tutorial, vreau să vă împărtășesc cum să utilizați acest lucru pentru propriile proiecte și cum afectează performanța și memoria pentru browserele majore.
Dar, înainte de a mă scufunda, permiteți-mi să împărtășesc de ce ai nevoie de membri privați, precum și de un mod alternativ de a "simula" membrii privați.
Simțiți-vă liber să vă ping pe Twitter dacă vreți să discutați despre acest articol: @deltakosh.
Când creați un obiect folosind JavaScript, puteți defini membri de valoare. Dacă doriți să controlați accesul la citire / scriere, aveți nevoie de accesori care pot fi definiți astfel:
var entitate = ; entity._property = "salut lume"; Object.defineProperty (entitate, "proprietate", get: function () return this._property;, set: functie (valoare) this._property = value; enumerable: true;
Procedând astfel, aveți control complet asupra operațiilor de citire și scriere. Problema este că _proprietate
membru este încă accesibil și poate fi modificat direct.
Acesta este exact motivul pentru care aveți nevoie de o modalitate mai robustă de a defini membri privați care pot fi accesați numai prin funcțiile obiectului.
Soluția este de a utiliza spațiul de închidere. Acest spațiu de memorie este construit pentru dvs. de către browser de fiecare dată când o funcție interioară are acces la variabile din domeniul unei funcții externe. Acest lucru poate fi uneori dificil, dar pentru subiectul nostru aceasta este o soluție perfectă.
Deci, să modificăm codul anterior pentru a utiliza această caracteristică:
var createProperty = funcția (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (value) actualValue = value; : Adevărat ); var entitate = ; var myVar = "salut lume"; createProperty (entitate, "proprietate", myVar);
În acest exemplu, createProperty
funcția are a Valoarea curentă
variabilă care poate vedea și seta funcțiile. Această variabilă va fi salvată în spațiul de închidere al funcțiilor de obținere și setare. Doar aceste două funcții pot vedea și actualiza acum Valoarea curentă
variabil! Misiune indeplinita!
Singura avertizare pe care o avem aici este că valoarea sursă (myVar
) este încă accesibilă. Deci, vine o altă versiune pentru o protecție mai robustă:
var createProperty = funcție (obj, prop) var currentValue = obj [prop]; Object.defineProperty (obj, prop, get: function () retur actualValue;, set: functie (valoare) currentValue = value;, enumerable: true, configurable: true); var entity = proprietate: "hello world"; createProperty (entitate, "proprietate");
Folosind această metodă, chiar și valoarea sursei este distrusă. Așa că misiunea sa realizat pe deplin!
Să aruncăm o privire la performanță.
Evident, spațiile de închidere sau chiar proprietățile sunt mai lente și mai scumpe decât o variabilă simplă. De aceea, acest articol se concentrează mai mult pe diferența dintre modul regulat și tehnica spațiului de închidere.
Pentru a confirma că abordarea spațiului de închidere nu este prea costisitoare în comparație cu modul standard, am scris acest punct de referință mic:
Tehnica de calcul…
Creez 1 milion de obiecte, toate cu un membru de proprietate. Apoi fac trei încercări:
Iată un tabel și o diagramă a rezultatelor:
Putem vedea că versiunea spațiului de închidere este întotdeauna mai rapidă decât versiunea obișnuită și în funcție de browser, poate fi o optimizare impresionantă.
Performanța Chrome este mai mică decât mă așteptam. S-ar putea să fie un bug astfel încât să fiu sigur că am contactat echipa Google pentru a afla ce se întâmplă aici. De asemenea, dacă doriți să testați modul în care se efectuează acest lucru în noul browser Microsoft Edge-Microsoft, care va fi livrat implicit cu Windows 10, îl puteți descărca aici.
Cu toate acestea, dacă ne uităm îndeaproape, putem constata că utilizarea spațiului de închidere sau chiar a unei proprietăți poate fi de zece ori mai lentă decât accesul direct la un membru. Așa că fiți avertizați și folosiți-l cu înțelepciune.
De asemenea, trebuie să verificăm dacă această tehnică nu consumă prea multă memorie. Pentru a compara memoria am scris aceste trei bucăți de cod:
var sampleSize = 1000000; var entități = []; // Crearea entităților pentru (var index = 0; index < sampleSize; index++) entities.push( property: "hello world (" + index + ")" );
var sampleSize = 1000000; var entități = []; // Adăugarea proprietății și utilizarea membrului local pentru a salva valoarea privată pentru (var index = 0; index < 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 entități = []; var createProperty = funcția (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (value) actualValue = value; : Adevărat ); // Adăugarea proprietății și utilizarea spațiului de închidere pentru a salva valoarea privată pentru (var index = 0; index < sampleSize; index++) var entity = ; var currentValue = "hello world (" + index + ")"; createProperty(entity, "property", currentValue); entities.push(entity);
Apoi am executat toate aceste trei coduri și am lansat profilul de memorie încorporat (exemplu aici folosind instrumentele F12):
Iată rezultatele pe care le am pe calculatorul meu:
Între spațiul de închidere și modul obișnuit, numai Chrome are rezultate ușor mai bune pentru versiunea spațiului de închidere. IE11 și Firefox utilizează un pic mai multă memorie, dar browserele sunt relativ comparabile - probabil că utilizatorii nu vor observa o diferență între browserele moderne.
S-ar putea să vă surprindă puțin, dar Microsoft are o grămadă de învățare gratuită pe multe subiecte JavaScript open source și suntem în misiunea de a crea mult mai mult cu Microsoft Edge. Check out-ul meu:
Sau seria de învățare a echipei noastre:
Și câteva instrumente gratuite: Visual Studio Community, Azure Trial și instrumente de testare cross-browser pentru Mac, Linux sau Windows.
După cum puteți vedea, proprietățile spațiului de închidere pot fi a modalitate foarte bună de a crea date cu adevărat private. Este posibil să aveți de a face față unei mici creșteri a consumului de memorie, dar din punctul meu de vedere acest lucru este destul de rezonabil (și la acel preț puteți avea o îmbunătățire excelentă a performanțelor față de utilizarea modului obișnuit).
Și apropo dacă vrei să-l încerci singură, găsești tot codul folosit aici. Există un bun "cum să" pe Azure Mobile Services aici.
Acest articol face parte din seriile de tehnologie web dev din Microsoft. Suntem încântați să împărtășim Microsoft Edge și noul EdgeHTML motor de randare cu tine. Obțineți mașini virtuale gratuite sau testați de la distanță pe dispozitivele Mac, iOS, Android sau Windows @ http://dev.modern.ie/.
Aflați JavaScript: Ghidul complet
Am creat un ghid complet care vă ajută să învățați JavaScript, indiferent dacă începeți doar ca dezvoltator web sau doriți să explorați subiecte mai avansate.