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.
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.
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.
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.
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.
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.
hasOwnProperty
om te controleren of een objecteigenschap niet van de prototypeketen isTerwijl 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.
in
operatorDe 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.
voor
in
LusDoor 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.
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).
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
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.