Jeg er stødt på noget rimelig besynderligt i dag – JavaScript fortolkeren i IE6, IE7 og FF2 opfører sig nemlig tilsyneladende sært når man opretter selvrefererende JavaScript Object Notation (JSON) objekter.
Betragt den første variabeltilskrivning jeg udfører i Firebug konsollen i Firefox:
>>> var json = { "foo": 42 };
Den evaluerer til et objekt der indeholder:
>>> json
Object foo=42
Hvis vi gerne vil have oprettet et JSON objekt der refererer til sig selv, kan man angive f.eks.:
>>> var json = { "foo": 42, "selfRef": json.foo };
Hvilket evaluerer til et objekt der indeholder:
>>> json
Object selfRef=42 foo=42
Omskriver man det en smule, så property’en foo tilgås på array form bliver værditilskrivningen til:
>>> var json = { "foo": 42, "selfRef": json["foo"] };
Og det går det lige så fint med, da det også evaluerer til:
>>> json
Object selfRef=42 foo=42
Filmen lader dog til at knække helt hvis den nøgle man anvender er et tal, hvilket er fint gyldigt iøvrigt:
>>> var json = { "2": 42, "selfRef": json["2"] };
Nu har vi nemlig kun objektet:
>>> json
Object 2=42
Så jeg tænkte at jeg enten havde fundet en generel implementationsfejl i JavaScript fortolkerne i IE og FF (hvilket må siges at være overvejende usandsynligt), eller også er mine forsøg herover fejlbehæftede. Sidste mulighed viste sig at være årsagen.
Det går nemlig fint at erklære cykliske JSON strukturer hvis de basis data der skal indgå i selvreferencerne allerede er erklærede på forhånd. Og det er de netop hvis man afprøver dette forløb:
>>> var json = { "foo": 42 };
>>> var json = { "foo": 42, "selfRef": json.foo };
>>> json
Object selfRef=42 foo=42
Hvis json.foo ikke indledningsvist havde været erklæret fejler den selvreferende erklæring:
>>> var json = { "foo": 42 };
>>> var json = "";
>>> var json = { "foo": 42, "selfRef": json.foo };
>>> json
Object foo=42
Så det var udelukkende på grund af weekenden der var lige om hjørnet, og fordi forsøget på at indsætte en hidtil utilskrevet talnøgle i JSON strukturen gjorde at “fejlen” fremstod. Man kan dog fortsat være lidt tvivlende overfor hvordan en tilskreven property bare kan forsvinde ud i den blå luft. Man kunne forvente at selfRef som minimum var tilstede og blot indeholdt værdien "undefined" eller endnu bedre null. Alternativt havde en kastet exception også været ok.