Ik heb onlangs Angular Cloud Data Connector ontwikkeld, waarmee Angular-ontwikkelaars cloudgegevens, met name Azure Mobile Services, kunnen gebruiken met behulp van webstandaarden zoals geïndexeerde DB. Ik probeerde een manier te creëren voor JavaScript-ontwikkelaars om privé-leden in te bedden in een object.
Mijn techniek voor dit specifieke geval is om te gebruiken wat ik 'sluitruimte' noem. In deze zelfstudie wil ik met u delen hoe u dit voor uw eigen projecten kunt gebruiken en hoe dit de prestaties en het geheugen voor de belangrijkste browsers beïnvloedt..
Maar laat me, voordat je erin duikt, vertellen waarom je misschien privé-leden nodig hebt, en ook een alternatieve manier om privéleden te "simuleren"..
Voel je vrij om me te pingen op Twitter als je dit artikel wilt bespreken: @deltakosh.
Wanneer u een object maakt met JavaScript, kunt u waardeleden definiëren. Als u lees- / schrijftoegang op hen wilt beheren, hebt u accessors nodig die als volgt kunnen worden gedefinieerd:
var entity = ; entity._property = "hallo wereld"; Object.defineProperty (entity, "property", get: function () return this._property;, set: function (value) this._property = value;, op te tellen: true, configurable: true);
Door dit te doen, hebt u de volledige controle over lees- en schrijfbewerkingen. Het probleem is dat de _eigendom
lid is nog steeds toegankelijk en kan direct worden gewijzigd.
Dit is precies waarom je een meer robuuste manier nodig hebt om privéleden te definiëren die alleen toegankelijk zijn via objectfuncties.
De oplossing is om sluitruimte te gebruiken. Deze geheugenruimte wordt door de browser voor u gemaakt telkens een innerlijke functie toegang heeft tot variabelen uit de reikwijdte van een externe functie. Dit kan soms lastig zijn, maar voor ons onderwerp is dit een perfecte oplossing.
Dus laten we de vorige code wijzigen om deze functie te gebruiken:
var createProperty = function (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (value) currentValue = value;, opsom: true, configureerbaar : true); var entity = ; var myVar = "hallo wereld"; createProperty (entity, "property", myVar);
In dit voorbeeld is de CreateProperty
functie heeft een huidige waarde
variabele die de get en set-functies kunnen zien. Deze variabele wordt opgeslagen in de sluitingsruimte van get en set-functies. Alleen deze twee functies kunnen nu het huidige waarde
variabele! Missie volbracht!
Het enige voorbehoud dat we hier hebben, is dat de bronwaarde (myVar
) is nog steeds toegankelijk. Dus hier komt nog een versie voor nog meer robuuste bescherming:
var createProperty = function (obj, prop) var currentValue = obj [prop]; Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (value) currentValue = value;, opsommen: true, configurable: true); var entity = property: "hello world"; createProperty (entity, "property");
Met behulp van deze methode wordt zelfs de bronwaarde vernietigd. Dus missie volledig volbracht!
Laten we nu eens kijken naar de prestaties.
Vanzelfsprekend zijn afsluitruimten of zelfs eigenschappen langzamer en duurder dan alleen een gewone variabele. Daarom is dit artikel meer gericht op het verschil tussen de reguliere manier en de sluitruimte-techniek.
Om te bevestigen dat de benadering van de sluitingsruimte niet te duur is in vergelijking met de standaardmanier, heb ik deze kleine benchmark geschreven:
Computing ...
Ik maak 1 miljoen objecten, allemaal met een propertylid. Dan doe ik drie tests:
Hier zijn een tabel en een grafiek van de resultaten:
We kunnen zien dat de afsluitruimteversie altijd sneller is dan de reguliere versie en afhankelijk van de browser, het kan een heel indrukwekkende optimalisatie zijn.
De prestaties van Chrome zijn minder dan ik had verwacht. Er is misschien een foutje om zeker te zijn, ik heb contact opgenomen met het Google-team om erachter te komen wat hier gebeurt. Ook als u wilt testen hoe dit presteert in de nieuwe browser van Microsoft Edge-Microsoft die standaard met Windows 10 wordt verzonden, kunt u dit hier downloaden.
Als we echter goed kijken, zien we dat het gebruik van sluitruimte of zelfs een eigenschap tien keer langzamer kan zijn dan directe toegang tot een lid. Dus wees gewaarschuwd en gebruik het verstandig.
We moeten ook controleren dat deze techniek niet te veel geheugen verbruikt. Om het geheugen te benchmarken heb ik deze drie kleine stukjes code geschreven:
var sampleSize = 1000000; var-entiteiten = []; // Entiteiten maken voor (var index = 0; index < sampleSize; index++) entities.push( property: "hello world (" + index + ")" );
var sampleSize = 1000000; var-entiteiten = []; // Eigenschap toevoegen en lokaal lid gebruiken om privéwaarde op te slaan voor (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-entiteiten = []; var createProperty = function (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (value) currentValue = value;, opsom: true, configureerbaar : true); // Eigenschap toevoegen en afsluitruimte gebruiken om persoonlijke waarde op te slaan voor (var index = 0; index < sampleSize; index++) var entity = ; var currentValue = "hello world (" + index + ")"; createProperty(entity, "property", currentValue); entities.push(entity);
Vervolgens heb ik al deze drie codes uitgevoerd en de ingesloten geheugenprofiler gelanceerd (bijvoorbeeld hier met behulp van F12-hulpmiddelen):
Dit zijn de resultaten die ik op mijn computer heb gekregen:
Tussen sluitingsruimte en normale manier heeft alleen Chrome iets betere resultaten voor de versie met sluitingsruimte. IE11 en Firefox gebruiken een beetje meer geheugen, maar de browsers zijn relatief vergelijkbaar - gebruikers zullen waarschijnlijk geen verschil merken in de moderne browsers.
Het zal je misschien een beetje verbazen, maar Microsoft heeft een heleboel gratis leren over veel open source JavaScript-onderwerpen, en we zijn op een missie om nog veel meer te maken met Microsoft Edge coming. Bekijk mijn eigen:
Of de leerserie van ons team:
En enkele gratis tools: Visual Studio Community, Azure Trial en cross-browser testtools voor Mac, Linux of Windows.
Zoals je ziet, kunnen de eigenschappen van de sluitruimte een zijn geweldige manier om echt privégegevens te maken. Je hebt misschien te maken met een kleine toename in geheugengebruik, maar vanuit mijn oogpunt is dit redelijk redelijk (en voor die prijs kun je een geweldige prestatieverbetering krijgen ten opzichte van het gebruik van de normale manier).
En trouwens, als u het zelf wilt proberen, vindt u hier alle code die hier wordt gebruikt. Er is een goede "how-to" op Azure Mobile Services hier.
Dit artikel maakt deel uit van de web dev tech-serie van Microsoft. We zijn verheugd om te delen Microsoft Edge en het nieuwe EdgeHTML-renderingengine met jou. Download gratis virtuele machines of test op afstand op uw Mac, iOS, Android of Windows-apparaat @ http://dev.modern.ie/.
Leer JavaScript: de complete gids
We hebben een complete handleiding samengesteld om u te helpen JavaScript te leren, of u net bent begonnen als een webontwikkelaar of dat u meer geavanceerde onderwerpen wilt verkennen.