Jeg har tidligere skrevet litt om problemer som kan oppstå når du sender et objekt til et annet vindu og så forsøker å teste hvilken klasse objektet er en instans av. Denne testen benytter instanceof-operatoren og slik det går frem av det tidligere innlegget oppfører ikke Microsoft Internet Explorer alltid slik en skulle forvente. Nå har jeg utvidet problemstillingen til også å teste variabler i andre vinduer og med flere browsere, for å finne ut når praksis er enig med teori.
Når du vil teste om et objekt er en instans av en klasse benyttes operatoren instanceof, for eksempel slik:
if(minVariabel instanceof minKlasse) { ... }
Denne testen skal være sann dersom minVariabel er en instans av klassen minKlasse. For å lage et objekt (en instans) av en klasse brukes new-operatoren, eksempelvis minVariabel = new minKlasse();
Poenget med instanceof-operatoren er at den gir deg mulighet til å teste hvilken klasse et objekt er hentet fra, og således kun benytte metoder og egenskaper du vet eksisterer for objekter av den klassen. Du kan med andre ord lage en metode som gjør forskjellige ting avhengig av klassen den tilhører, noe som igjen kan gi mer kompakt og oversiktlig kode.
Ideen er god, men så viser det seg at teori og praksis ikke stemmer. I det tidligere blogginnlegget er det nevnt at MSIE ikke kan teste objekter sendt som argumenter fra et annet vindu. Spørsmålet var nå om det eksisterte andre varianter der testene også feilet, og hvilke browsere som sluttet å fungere.
Til å hjelpe meg med dette har jeg laget tre varianter av samme test og lagt det ut som et eget testcase. Dokumentene der er holdt på engelsk eftersom jeg vil kunne bruke det i bugrapporter. Første variant (#1) av testen kaller en funksjon i et (annet) vindu med lokale variabler som argument. Det er samme problemområde som nevnt i det tidligere blogginnlegget, og hvor MSIE feiler. Funksjonen kalles to ganger, først med en primitiv tall-verdi, det vil si en vanlig tall-variabel laget med var notNumberClass = 8;. Andre gang kalles den med et objekt skapt fra klassen Number() med var isNumberClass = new Number(8);. Resultatet av det første kallet skal være at variabelen (objektet) ikke er instans av noen klasse, mens det andre kallet skal definere objektet som en instans av klassene Number og Object (alle objekter i JavaScript nedstammer fra Object).
Andre variant (#2) snur om på problemstillingen ved at den kaller en lokal funksjon, det vil si i ett og samme vindu, mens argumentet flyttes rundt. Igjen gjøre testen med både en primitiv verdi og en instans av Number-klassen og skal i utgangspunktet gi samme resultater som for #1. Jeg var usikker på om problemet ville være likt for de som ikke takler #1, men ut fra resultatet ser de ut til å betrakte det som samme problem.
Siste variant (#3) kaller en funksjon hvor variablene befinner seg i samme vindu som funksjonen, det vil si at både funksjon og argument flyttes rundt. Den variabelen som testes er dermed lokal til vinduet funksjonen befinner seg i. Her er det ingen problemer overhodet og alle browsere gir riktige resultater.
Jeg har sjekket testcaset med fire browsere:
- Microsoft Internet Explorer 6
- Mozilla 1.5
- Opera 7.23
- Konqueror 3.1-15 Red Hat
Av disse er det bare Mozilla 1.5 som gjør tingene riktig i alle 3 testene. De tre andre får riktige svar i test #3, men nekter for at objektet er en instans av klassene Number og Object i test #1 og #2. Foreløpig har jeg ikke lest nok av ECMA-262 til å forstå hvorfor de oppfører seg om de gjør, men ut fra definisjonen av instanceof finner jeg det noe overraskende at den ikke skal fungere på tvers av vinduer/rammer.