JavaScript Slik legger du inn private medlemmer i et objekt

Jeg har nylig utviklet Angular Cloud Data Connector, som gjør at Angular-utviklere kan bruke sky data, spesielt Azure Mobile Services, ved hjelp av webstandarder som indeksert DB. Jeg prøvde å lage en måte for JavaScript-utviklere å legge inn private medlemmer i en gjenstand. 

Min teknikk for dette spesielle tilfellet er å bruke det jeg kaller "lukkingsrom". I denne veiledningen vil jeg dele med deg hvordan du bruker dette til dine egne prosjekter, og hvordan det påvirker ytelse og minne for de store nettleserne.

Men før du drar inn i det, la meg dele hvorfor du kanskje trenger private medlemmer, samt en alternativ måte å "simulere" private medlemmer på.

Ta gjerne på meg på Twitter hvis du vil diskutere denne artikkelen: @deltakosh.

1. Hvorfor bruke private medlemmer

Når du oppretter et objekt ved hjelp av JavaScript, kan du definere verdi medlemmer. Hvis du vil kontrollere lese / skrive tilgang på dem, trenger du accessors som kan defineres slik:

var enhet = ; entity._property = "hei verden"; Object.defineProperty (enhet, "egenskap", get: function () return this._property;, sett: funksjon (verdi) this._property = value;, tallrik: sann, konfigurerbar: true);

Ved å gjøre dette har du full kontroll over lese- og skriveoperasjoner. Problemet er at _eiendom medlem er fortsatt tilgjengelig og kan endres direkte.

Dette er nøyaktig hvorfor du trenger en mer robust måte å definere private medlemmer som bare kan nås av objektets funksjoner.

2. Bruke Lukk Space

Løsningen er å bruke lukningsplass. Denne minnesplassen er bygget for deg av nettleseren hver gang en indre funksjon har tilgang til variabler fra omfanget av en ytre funksjon. Dette kan være vanskelig noen ganger, men for vårt emne er dette en perfekt løsning.

Så la oss endre den forrige koden for å bruke denne funksjonen:

var createProperty = funksjon (obj, prop, currentValue) Object.defineProperty (obj, prop, get: funksjon () return currentValue;, sett: funksjon (verdi) currentValue = value;, tallverdig: sann, konfigurerbar : sant);  var enhet = ; var myVar = "hei verden"; createProperty (enhet, "eiendom", myVar);

I dette eksemplet er createProperty funksjonen har a nåværende verdi variabel som får og sett funksjoner kan se. Denne variabelen skal lagres i lukkingsområdet for get og set-funksjonene. Bare disse to funksjonene kan nå se og oppdatere nåværende verdi variabel! Oppdrag utført!

Den eneste advarselen vi har her er at kildeværdien (myVar) er fortsatt tilgjengelig. Så her kommer en annen versjon for enda mer robust beskyttelse:

var createProperty = funksjon (obj, prop) var currentValue = obj [prop]; Object.defineProperty (obj, prop, get: funksjon () return currentValue;, sett: funksjon (verdi) currentValue = value;, tallverdig: true, konfigurerbar: true);  var enhet = eiendom: "hallo verden"; createProperty (enhet, "eiendom");

Ved hjelp av denne metoden blir selv kildeverdien ødelagt. Så oppdraget fullført!

3. Ytelsesoverveielser

La oss nå se på ytelsen.

Tydeligvis er lukkeflater eller til og med egenskaper langsommere og dyrere enn bare en ren variabel. Det er derfor denne artikkelen fokuserer mer på forskjellen mellom den vanlige måten og lukkeplatteteknikken.

For å bekrefte lukkingsrommet tilnærming er ikke for dyrt i forhold til standardveien skrev jeg dette lille referansen:

       
Computing ...

Jeg lager 1 million objekter, alle med et eiendomsmedlem. Så gjør jeg tre tester:

  • Gjør 1 million tilfeldig tilgang til eiendommen.
  • Gjør 1 million tilfeldige tilgang til "lukkingsrom" -versjonen.
  • Gjør 1 million tilfeldige tilgang til den vanlige få / sett-versjonen.

Her er et bord og et diagram over resultatene:

Vi kan se at lukkestedsversjonen alltid er raskere enn den vanlige versjonen og avhengig av nettleseren, det kan være en virkelig imponerende optimalisering.

Chrome ytelse er mindre enn jeg forventet. Det kan være en feil for å være sikker, jeg kontaktet Googles team for å finne ut hva som skjer her. Også hvis du vil teste hvordan dette virker i Microsoft Edge-Microsofts nye nettleser som sender standard med Windows 10, kan du laste den ned her.

Men hvis vi ser nøye ut, kan vi finne at bruk av lukkingsrom eller til og med en eiendom kan være ti ganger langsommere enn direkte tilgang til et medlem. Så vær advart og bruk det klokt.

4. Minnefotavtrykk

Vi må også sjekke at denne teknikken ikke bruker for mye minne. For å benchmark minne skrev jeg disse tre små kodene:

Referansekode

var sampleSize = 1000000; var enheter = []; // Opprette enheter for (var index = 0; indeks < sampleSize; index++)  entities.push( property: "hello world (" + index + ")" ); 

Vanlig måte

var sampleSize = 1000000; var enheter = []; // Legge til eiendom og bruke lokalt medlem for å lagre privat verdi for (var index = 0; indeks < 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); 

Lukk Space Version

var sampleSize = 1000000; var enheter = []; var createProperty = funksjon (obj, prop, currentValue) Object.defineProperty (obj, prop, get: funksjon () return currentValue;, sett: funksjon (verdi) currentValue = value;, tallverdig: sann, konfigurerbar : sant);  // Legge til eiendom og bruke lukket plass for å lagre privat verdi for (var index = 0; indeks < sampleSize; index++)  var entity = ; var currentValue = "hello world (" + index + ")"; createProperty(entity, "property", currentValue); entities.push(entity); 

Så kjørte jeg alle disse tre kodene og lanserte den innebygde minnesprofilen (eksempel her med F12-verktøy):

Her er resultatene jeg fikk på min datamaskin:

Mellom lukkeplass og vanlig måte har bare Chrome noe bedre resultater for lukkutrykksversjonen. IE11 og Firefox bruker litt mer minne, men nettleserne er relativt sammenlignbare. Brukerne vil sannsynligvis ikke merke en forskjell på tvers av de moderne nettleserne.

Flere hands-on med JavaScript

Det kan kanskje overraske deg litt, men Microsoft har en mengde gratis læring på mange open source JavaScript-emner, og vi er på oppdrag for å skape mye mer med Microsoft Edge. Sjekk ut min egen:

  • Introduksjon til WebGL 3D med HTML5 og Babylon.JS
  • Bygg en enkeltside applikasjon med ASP.NET og AngularJS
  • Skjærekantgrafikk i HTML

Eller vårt lags læringsserie:

  • Praktiske ytelsestips for å gjøre HTML / JavaScript raskere (en syvdelte serie fra lydhør design til uformelle spill til ytelsesoptimalisering)
  • Den moderne webplattformen Jump Start (grunnleggende for HTML, CSS og JS)
  • Utvikle Universal Windows Apps med HTML og JavaScript Jump Start (bruk JS du allerede har opprettet for å bygge en app)

Og noen gratis verktøy: Visual Studio Community, Azure Trial, og tverrbrowser testing verktøy for Mac, Linux eller Windows.

Konklusjon

Som du kan se, kan lukkearealegenskaper være en Flott måte å skape virkelig private data på. Du må kanskje håndtere en liten økning i minnekonsumet, men fra mitt synspunkt er dette ganske rimelig (og til den prisen kan du få en god ytelsesforbedring i forhold til vanlig måte).

Og forresten hvis du vil prøve det selv, vennligst finn all koden som brukes her. Det er en god "how-to" på Azure Mobile Services her.

Denne artikkelen er en del av web dev-teknologiserien fra Microsoft. Vi er glade for å dele Microsoft Edge og den nye EdgeHTML rendering motor med deg. Få gratis virtuelle maskiner eller test eksternt på Mac, IOS, Android eller Windows-enheten @ http://dev.modern.ie/.

Lær JavaScript: Den komplette veiledningen

Vi har bygget en komplett guide for å hjelpe deg med å lære JavaScript, enten du er bare i gang som webutvikler eller du vil utforske mer avanserte emner.