Jag har nyligen utvecklat Angular Cloud Data Connector, som gör det möjligt för Angular-utvecklare att använda molndata, särskilt Azure Mobile Services, med hjälp av webbstandarder som indexerad DB. Jag försökte skapa ett sätt för JavaScript-utvecklare att integrera privata medlemmar i ett objekt.
Min teknik för detta specifika fall är att använda det jag kallar "stängningsutrymme". I denna handledning vill jag dela med dig hur man använder det här för egna projekt och hur det påverkar prestanda och minne för de stora webbläsarna.
Men innan du dyker in i det, låt mig dela varför du kanske behöver privata medlemmar, samt ett alternativt sätt att "simulera" privata medlemmar.
Känn dig fri att pinga mig på Twitter om du vill diskutera den här artikeln: @deltakosh.
När du skapar ett objekt med hjälp av JavaScript kan du definiera värdemedlemmar. Om du vill kontrollera läs / skrivåtkomst på dem behöver du accessors som kan definieras så här:
var enhet = ; entity._property = "hej värld"; Object.defineProperty (enhet, "egenskap", get: function () return this._property;, set: funktion (värde) this._property = value;, uppräkningsbar: sant, konfigurerbar: true);
Genom att göra detta har du full kontroll över läs- och skrivoperationer. Problemet är att _fast egendom
medlemmen är fortfarande tillgänglig och kan ändras direkt.
Det är just därför du behöver ett mer robust sätt att definiera privata medlemmar som endast kan nås av objektets funktioner.
Lösningen är att använda stängningsutrymme. Det här minnesutrymmet är byggt för dig av webbläsaren varje gång en inre funktion har tillgång till variabler från ramen för en yttre funktion. Detta kan vara knepigt ibland, men för vårt ämne är det här en perfekt lösning.
Så låt oss ändra den tidigare koden för att använda den här funktionen:
var skapaProperty = funktion (obj, prop, currentValue) Object.defineProperty (obj, prop, get: funktion () return currentValue;, set: funktion (värde) currentValue = value;, uppräkningsbar: sant, konfigurerbar : Sann ); var enhet = ; var myVar = "hej värld"; createProperty (enhet, "egenskap", myVar);
I det här exemplet är createProperty
funktionen har a nuvarande värde
variabel som får och sätter funktioner kan se. Denna variabel kommer att sparas i stängningsutrymmet för get och set-funktioner. Endast dessa två funktioner kan nu se och uppdatera nuvarande värde
variabel! Uppdrag slutfört!
Det enda som vi har här är att källvärdet (myVar
) är fortfarande tillgänglig. Så här kommer en annan version för ännu mer robust skydd:
var createProperty = funktion (obj, prop) var currentValue = obj [prop]; Object.defineProperty (obj, prop, get: funktion () return currentValue;, set: funktion (värde) currentValue = value;, talbar: true, configable: true); var enhet = egendom: "hej värld"; createProperty (enhet, "egenskap");
Med hjälp av denna metod förstörs även källvärdet. Så uppdraget är fullt uppnått!
Låt oss nu titta på prestanda.
Självklart är stängningsutrymmen eller till och med egenskaper långsammare och dyrare än bara en vanlig variabel. Därför fokuserar denna artikel mer på skillnaden mellan det vanliga sättet och stängningsutrymmet tekniken.
För att bekräfta stängningsutrymmet är inte för dyrt jämfört med det vanliga sättet skrev jag det här lilla riktmärket:
Datoranvändning…
Jag skapar 1 miljon objekt, alla med en fastighetsmedlem. Då gör jag tre tester:
Här är en tabell och ett diagram över resultaten:
Vi kan se att stängningsutrymmesversionen alltid är snabbare än den vanliga versionen och beroende på webbläsaren, det kan vara en riktigt imponerande optimering.
Chrome-prestanda är mindre än vad jag förväntade mig. Det kan hända att jag är säker på att jag kontaktade Googles team för att ta reda på vad som händer här. Också om du vill testa hur detta fungerar i Microsoft Edge-Microsofts nya webbläsare som skickas som standard med Windows 10, kan du ladda ner det här.
Men om vi tittar noga kan vi konstatera att det går att använda stängningsutrymme eller till och med en fastighet kan vara tio gånger långsammare än direkt tillgång till en medlem. Var så varnas och använd det klokt.
Vi måste också kontrollera att denna teknik inte förbrukar för mycket minne. För att benchmark minne skrev jag dessa tre små bitar av kod:
var sampleSize = 1000000; var enheter = []; // Skapa enheter för (var index = 0; index < sampleSize; index++) entities.push( property: "hello world (" + index + ")" );
var sampleSize = 1000000; var enheter = []; // Lägga till egendom och använd lokalmedlem för att spara privatvärde för (varindex = 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 enheter = []; var skapaProperty = funktion (obj, prop, currentValue) Object.defineProperty (obj, prop, get: funktion () return currentValue;, set: funktion (värde) currentValue = value;, uppräkningsbar: sant, konfigurerbar : Sann ); // Lägga till egendom och använda stängningsutrymme för att spara privatvärde för (varindex = 0; index < sampleSize; index++) var entity = ; var currentValue = "hello world (" + index + ")"; createProperty(entity, "property", currentValue); entities.push(entity);
Sedan sprang jag alla dessa tre koder och lanserade den inbyggda minnesprofilen (exempel här med hjälp av F12-verktyg):
Här är resultaten jag fick på min dator:
Mellan stängningsutrymme och vanligt sätt har endast Chrome något bättre resultat för stängningsutrymmet. IE11 och Firefox använder lite mer minne, men webbläsarna är relativt jämförbara. Användarna kommer antagligen inte märka någon skillnad över de moderna webbläsarna.
Det kan kanske överraska dig lite, men Microsoft har en massa gratis lärande på många JavaScript-ämnen med öppen källkod, och vi har ett uppdrag att skapa mycket mer med Microsoft Edge. Kolla in min egen:
Eller vårt lags inlärningsserie:
Och några gratis verktyg: Visual Studio Community, Azure Trial och testverktyg för webbläsare för Mac, Linux eller Windows.
Som du kan se kan stängningsutrymmeegenskaper vara en Bra sätt att skapa riktigt privata data. Det kan hända att du måste hantera en liten ökning av minneskonsumtionen, men ur min synvinkel är det ganska rimligt (och till det priset kan du få en bra prestandaförbättring jämfört med det vanliga sättet).
Och förresten om du vill prova det själv, vänligen hitta all koden som används här. Det finns en bra "hur-till" på Azure Mobile Services här.
Den här artikeln är en del av web dev-tekniken från Microsoft. Vi är glada att dela Microsoft Edge och den nya EdgeHTML-återgivningsmotor med dig. Få gratis virtuella maskiner eller testa fjärran på din Mac, iOS, Android eller Windows-enheten @ http://dev.modern.ie/.
Lär dig JavaScript: Den fullständiga guiden
Vi har byggt en komplett guide för att hjälpa dig att lära dig JavaScript, oavsett om du precis börjat som webbutvecklare eller vill utforska mer avancerade ämnen.