Werken met objecten en eigenschappen

Een complex object kan elke toegestane JavaScript-waarde bevatten. In de volgende code maak ik een Voorwerp() object genoemd myObject en voeg vervolgens eigenschappen toe die de meerderheid van de beschikbare waarden in JavaScript vertegenwoordigen.


Complexe objecten

Voorbeeld: sample29.html

 

Het eenvoudige concept om hier te leren is dat complexe objecten kunnen bevatten of verwijzen naar alles dat je in JavaScript nominaal kunt uitdrukken. Je moet niet verbaasd zijn als je dit ziet gebeuren, omdat alle oorspronkelijke objecten kunnen worden gemuteerd. Dit geldt zelfs voor Draad(), Aantal(), en Boolean () waarden in hun objectvorm, d.w.z. wanneer ze zijn gemaakt met de nieuwe operator.


Complexe objecten inkapselen op een programmatisch voordelige manier

De Voorwerp(), Array (), en Functie() objecten kunnen andere complexe objecten bevatten. In het volgende voorbeeld demonstreer ik dit door een objectstructuur in te stellen met Voorwerp() voorwerpen.

Voorbeeld: sample30.html

 

Hetzelfde kan gedaan worden met een Array () object (ook bekend als multidimensionale array), of met een Functie() voorwerp.

Voorbeeld: sample31.html

 

Het belangrijkste concept om hier weg te nemen is dat sommige van de complexe objecten zijn ontworpen om andere objecten op een programmatisch voordelige manier in te kapselen.


De eigenschappen van een object verkrijgen, instellen en bijwerken met behulp van puntnotatie of haakjesnotatie

We kunnen de eigenschappen van een object ophalen, instellen of bijwerken met behulp van puntnotatie of haakjesnotatie.

In het volgende voorbeeld demonstreer ik puntnotatie, die wordt bereikt door de objectnaam gevolgd door een punt te gebruiken en vervolgens gevolgd door de eigenschap om te krijgen, in te stellen of bij te werken (bijv.., objectName.property).

Voorbeeld: sample32.html

 

Puntnotatie is de meest voorkomende notatie voor het verkrijgen, instellen of bijwerken van de eigenschappen van een object.

Bracketnotatie, tenzij vereist, wordt niet zo vaak gebruikt. In het volgende voorbeeld vervang ik de puntnotatie die in het vorige voorbeeld is gebruikt, met haakjesnotatie. De objectnaam wordt gevolgd door een openingshaak, de eigenschapnaam (tussen aanhalingstekens) en vervolgens een sluitingshaak:

Voorbeeld: sample33.html

 

Bracketnotatie kan erg handig zijn wanneer u toegang tot een eigenschapsleutel nodig hebt en waarmee u moet werken is een variabele die een tekenreekswaarde bevat die de eigenschapsnaam vertegenwoordigt. In het volgende voorbeeld demonstreer ik het voordeel van de notatie van de haakjes boven de puntnotatie door deze te gebruiken om toegang te krijgen tot de eigenschap foobar. Ik doe dit met behulp van twee variabelen die, wanneer ze worden samengevoegd, de tekenreeksversie van de eigenschapssleutel produceren foobarObject.

Voorbeeld: sample34.html

 

Bovendien kan haaknotatie handig zijn voor het ophalen van propertynamen die ongeldige JavaScript-id's zijn. In de volgende code gebruik ik een gereserveerde sleutelwoord en een gereserveerde sleutelwoord als een eigenschap (geldig als een tekenreeks) die alleen de haakjesnotatie kan gebruiken.

Voorbeeld: sample35.html

 

Omdat objecten andere objecten kunnen bevatten, cody.object.object.object.object of Cody [ 'object'] [ 'doel'] [ 'doel'] [ 'doel'] kan soms worden gezien. Dit wordt objectketening genoemd. De inkapseling van objecten kan eindeloos doorgaan.

Objecten kunnen worden gewijzigd in JavaScript, wat betekent dat ze op elk moment op de meeste objecten kunnen worden opgehaald, ingesteld of bijgewerkt. Door de beugelnotatie te gebruiken (bijv., Cody [ 'leeftijd']), kunt u associatieve arrays nabootsen die in andere talen zijn gevonden.

Als een eigenschap in een object een methode is, hoeft u alleen maar de. Te gebruiken () operators (bijv., cody.getGender ()) om de eigenschapmethode aan te roepen.


Objecteigenschappen verwijderen

De verwijderen operator kan worden gebruikt om eigenschappen van een object volledig te verwijderen. In het volgende codefragment verwijderen we de bar eigendom van de foo voorwerp.

Voorbeeld: sample36.html

 

verwijderen zullen geen eigenschappen verwijderen die gevonden zijn in de prototypeketen.

Verwijderen is de enige manier om een ​​eigenschap daadwerkelijk uit een object te verwijderen. Een eigenschap instellen op onbepaald of nul wijzigt alleen de waarde van de eigenschap. Het verwijdert de eigenschap niet van het object.


Hoe verwijzingen naar objecteigenschappen zijn opgelost

Als u probeert toegang te krijgen tot een eigenschap die niet in een object staat, probeert JavaScript de eigenschap of methode te vinden met behulp van de prototypeketen. In het volgende voorbeeld maak ik een array en probeer ik een geroepen eigenschap te openen foo dat is nog niet gedefinieerd. Je zou denken dat omdat myArray.foo is geen eigendom van de myArray object, zal JavaScript onmiddellijk terugkeren onbepaald. Maar JavaScript ziet er op twee andere plaatsen uit (Array.prototype en dan Object.prototype) voor de waarde van foo voordat het terugkeert onbepaald.

Voorbeeld: sample37.html

 

het eigendom. Als het de eigenschap heeft, wordt de waarde van de eigenschap geretourneerd en treedt er geen erfenis op omdat de prototypeketen niet wordt gebruikt. Als de instantie de eigenschap niet heeft, zoekt JavaScript deze vervolgens op de constructorfunctie van het object prototype voorwerp.

Alle objectexemplaren hebben een eigenschap die een geheime link is (aka __proto__) aan de constructorfunctie die de instantie heeft gemaakt. Deze geheime link kan worden gebruikt om de constructorfunctie te pakken, met name de prototype-eigenschap van de constructorfunctie van de instantie.

Dit is een van de meest verwarrende aspecten van objecten in JavaScript. Maar laten we dit uitpraten. Onthoud dat een functie ook een object met eigenschappen is. Het is logisch om toe te staan ​​dat objecten eigenschappen van andere objecten overnemen. Net als zeggen: "Hé object B, ik zou graag willen dat je alle eigenschappen deelt die object A heeft." JavaScript koppelt dit allemaal standaard voor native objecten via de prototype voorwerp. Wanneer u uw eigen constructorfuncties maakt, kunt u ook prototypeketting gebruiken.

Hoe JavaScript dit precies doet, is verwarrend totdat je het ziet zoals het is: slechts een reeks regels. Laten we een array maken om de. Te onderzoeken prototype eigendom dichterbij.

Voorbeeld: sample38.html

 

Onze Array () instantie is een object met eigenschappen en methoden. Naarmate we een van de array-methoden gebruiken, zoals join (), laten we ons afvragen: heeft de instantie myArray gemaakt van de Array () constructor heeft zijn eigen join () methode? Laten we het controleren.

Voorbeeld: sample39.html

 

Nee dat doet het niet. Maar myArray heeft toegang tot de join () methode alsof het zijn eigen eigendom is. Wat is hier gebeurd? Nou, je zag de prototypeketen gewoon in actie. We hebben een eigenschap geopend die, hoewel niet opgenomen in het object myArray, ergens anders door JavaScript kan worden gevonden. Dat ergens anders is heel specifiek. Wanneer de Array () constructor is gemaakt door JavaScript, the join () methode is (onder andere) toegevoegd als een eigenschap van de prototype eigendom van Array ().

Als u probeert toegang te krijgen tot een eigenschap op een object dat deze niet bevat, zoekt JavaScript in de prototype ketting voor deze waarde. Eerst zal het kijken naar de constructorfunctie die het object heeft gemaakt (bijv., reeks) en inspecteer het prototype (bijv., Array.prototype) om te zien of de woning daar te vinden is. Als het eerste prototypeobject niet de eigenschap heeft, blijft JavaScript de keten opzoeken naar de constructor achter de oorspronkelijke constructor. Het kan dit helemaal tot het einde van de keten doen.

Waar eindigt de keten? Laten we het voorbeeld opnieuw bekijken en de toLocaleString () methode op myArray.

Voorbeeld: sample40.html

 

De toLocaleString () methode is niet gedefinieerd binnen de myArray voorwerp. Dus de prototypekettingregel wordt aangeroepen en JavaScript zoekt naar de eigenschap in de reeks constructors prototype-eigenschap (bijv., Array.prototype). Het is er ook niet, dus de kettingregel wordt opnieuw opgeroepen en we zoeken naar het eigendom in de Voorwerp() prototype eigendom (Object.prototype). En ja, het is daar te vinden. Als JavaScript daar niet was gevonden, zou dit een fout hebben opgeleverd die beweert dat het eigendom was onbepaald.

Omdat alle prototype-eigenschappen objecten zijn, is de laatste schakel in de keten Object.prototype. Er is geen andere constructor prototype eigenschap die kan worden onderzocht.

Er staat een heel hoofdstuk voor de boeg dat de prototypeketen in kleinere delen opsplitst, dus als dit helemaal verloren was, lees dan dat hoofdstuk en kom dan terug op deze uitleg om je begrip te verharden. Ik hoop dat u uit dit korte lezen van de kwestie begrijpt dat wanneer een eigenschap niet wordt gevonden (en geacht wordt) onbepaald), Heeft JavaScript gekeken naar verschillende prototypeobjecten om te bepalen of een eigenschap dat is onbepaald. Er wordt altijd een opzoekactie uitgevoerd en dit opzoekproces is de manier waarop JavaScript zowel overerving als zoekopdrachten naar eenvoudige eigenschappen verwerkt.


Gebruik makend van hasOwnProperty om te controleren of een objecteigenschap niet van de prototypeketen is

Terwijl de in operator kan eigenschappen van een object controleren, inclusief eigenschappen van de prototypeketen, de hasOwnProperty methode kan een object controleren op een eigenschap die niet afkomstig is van de prototypeketen.

In het volgende voorbeeld willen we weten of myObject bevat de eigenschap foo, en dat het de eigenschap niet ervaart uit de prototypeketen. Om dit te doen, vragen we of myObject heeft zijn eigen eigenschap genaamd foo.

Voorbeeld: sample41.html

 

De hasOwnProperty methode moet worden gebruikt als u wilt bepalen of een eigenschap lokaal is voor een object of wordt geërfd van de prototypeketen.


Controleren of een object een gegeven eigenschap bevat met behulp van de in operator

De in operator wordt gebruikt om te verifiëren (waar of niet waar) als een object een bepaalde eigenschap bevat. In dit voorbeeld controleren we of foo is een eigendom in myObject.

Voorbeeld: sample42.html

 

U moet zich ervan bewust zijn dat de in operator controleert niet alleen op eigenschappen in het object waarnaar wordt verwezen, maar ook op alle eigenschappen die het object erft via de prototype keten. Daarom zijn dezelfde zoekregels voor eigenschappen van toepassing en wordt de eigenschap, indien niet in het huidige object, gezocht op de prototype keten.

Dit betekent dat myObject in de vorige sample eigenlijk een bevat toString eigendomsmethode via de prototype keten (Object.prototype.toString), zelfs als we er geen hebben opgegeven (bijv., myObject.toString = 'foo').

Voorbeeld: sample43.html

 

In het laatste codevoorbeeld bevindt de eigenschap toString zich niet letterlijk in het object myObject. Het is echter geërfd van Object.prototype, en zo de in exploitant concludeert dat myObject heeft in feite een geërfd toString () eigenschap methode.


Opsommen (Loop Over) de eigenschappen van een object met behulp van de voor in Lus

Door het gebruiken van voor in, we kunnen lus over elke eigenschap in een object. In de volgende steekproef gebruiken we de voor in lus om de eigenschapnamen uit het cody-object op te halen.

Voorbeeld: sample44.html

 

De voor in loop heeft een nadeel. Het zal niet alleen toegang krijgen tot de eigenschappen van het specifieke object dat wordt omgeleid. Het zal ook in de loop alle eigenschappen omvatten die (via de prototypeketting) door het object zijn geërfd. Dus, als dit niet het gewenste resultaat is, en meestal niet, moeten we een simpele gebruiken als statement binnen de lus om ervoor te zorgen dat we alleen toegang hebben tot de eigenschappen in het specifieke object waarover we een lus maken. Dit kan gedaan worden door de hasOwnProperty () methode overgenomen door alle objecten.

De volgorde waarin de eigenschappen in de lus worden benaderd, is niet altijd de volgorde waarin ze binnen de lus worden gedefinieerd. Bovendien is de volgorde waarin u eigenschappen hebt gedefinieerd niet noodzakelijk de volgorde waarin ze worden geopend.

Alleen eigenschappen die opsombaar zijn (dat wil zeggen beschikbaar bij lusvorming over de eigenschappen van een object) worden weergegeven met de voor in lus. De constructoreigenschap wordt bijvoorbeeld niet weergegeven. Het is mogelijk om te controleren welke eigenschappen opsombaar zijn met de propertyIsEnumerable () methode.


Host-objecten en native objecten

Houd er rekening mee dat de omgeving (bijvoorbeeld een webbrowser) waarin JavaScript wordt uitgevoerd, doorgaans host-objecten bevat. Host-objecten maken geen deel uit van de ECMAScript-implementatie, maar zijn tijdens de uitvoering beschikbaar als objecten. Natuurlijk hangt de beschikbaarheid en het gedrag van een hostobject volledig af van wat de hostomgeving biedt.

In de webbrowseromgeving worden bijvoorbeeld het venster / hoofd-object en alle bijbehorende objecten (met uitzondering van wat JavaScript biedt) beschouwd als hostobjecten.

In het volgende voorbeeld onderzoek ik de eigenschappen van de venster voorwerp.

Voorbeeld: sample45.html

 

U hebt misschien gemerkt dat native JavaScript-objecten niet tussen de hostobjecten staan. Het komt vrij vaak voor dat een browser onderscheid maakt tussen hostobjecten en native objecten.

Omdat het om webbrowsers gaat, is de bekendste van alle gehoste objecten de interface voor het werken met HTML-documenten, ook wel bekend als de DOM. Het volgende voorbeeld is een methode om alle objecten in het bestand op te nemen window.document object geleverd door de browseromgeving.

Voorbeeld: sample46.html

 

Wat ik hier wil leren is dat de JavaScript-specificatie zich niet bezig houdt met hostobjecten en omgekeerd. Er is een scheidslijn tussen wat JavaScript biedt (bijv. JavaScript 1.5, ECMA-262, Edition 3 versus Mozilla's JavaScript 1.6, 1.7, 1.8, 1.8.1, 1.8.5) en wat de hostomgeving biedt, en deze twee zouden niet moeten verward zijn.

De gastheeromgeving (bijvoorbeeld een webbrowser) die JavaScript-code uitvoert, levert typisch het hoofd-object (bijv. Een vensterobject in een webbrowser) waar de oorspronkelijke gedeelten van de taal worden opgeslagen samen met gastheerobjecten (bijv.., window.location in een webbrowser) en door de gebruiker gedefinieerde objecten (bijvoorbeeld de code die u schrijft om in de webbrowser te worden uitgevoerd).

Soms zal een webbrowserfabrikant, als host van de JavaScript-interpreter, een JavaScript-versie doorsturen of toekomstige specificaties aan JavaScript toevoegen voordat deze zijn goedgekeurd (bijv. Mozilla Firefox JavaScript 1.6, 1.7, 1.8, 1.8.1, 1.8). 5).


Objecten verbeteren en uitbreiden met Underscore.js

JavaScript 1.5 ontbreekt als het tijd is om objecten serieus te manipuleren en te beheren. Als u JavaScript in een webbrowser gebruikt, zou ik hier graag vetgedrukt zijn en het gebruik van Underscore.js aanbevelen wanneer u meer functionaliteit nodig hebt dan wordt geboden door JavaScript 1.5. Underscore.js biedt de volgende functionaliteit voor het omgaan met objecten.

Deze functies werken op alle objecten en matrices:

  • elk()
  • kaart()
  • verminderen()
  • reduceRight ()
  • detecteren ()
  • select ()
  • verwerpen ()
  • allemaal()
  • ieder()
  • include ()
  • beroep doen op()
  • plukken()
  • max ()
  • min ()
  • sorteer op()
  • sortIndex ()
  • toArray ()
  • grootte()

Deze functies werken op alle objecten:

  • sleutels ()
  • waarden ()
  • functies ()
  • uitbreiden()
  • clone ()
  • tik()
  • is gelijk()
  • is leeg()
  • isElement ()
  • IsArray ()
  • isArguments
  • isFunction ()
  • isString ()
  • ISNUMBER
  • isBoolean
  • IsDate
  • isRegExp
  • isNaN
  • is niets
  • isUndefined

Conclusie

Ik vind deze bibliotheek leuk omdat deze gebruikmaakt van de nieuwe native toevoegingen aan JavaScript waar browsers ze ondersteunen, maar ook dezelfde functionaliteit biedt aan browsers die dat niet doen, en dit alles zonder de native implementatie van JavaScript te veranderen, tenzij het moet.

Voordat u Underscore.js gaat gebruiken, moet u ervoor zorgen dat de functionaliteit die u nodig hebt niet al wordt geboden door een JavaScript-bibliotheek of -raamwerk dat mogelijk al in uw code wordt gebruikt.