JavaScript - fra skældsord til spændende mulighed

by DotNetNerd 26. June 2008 08:52

Ligesom for rigtigt mange andre udviklere har javascript altid været et skældsord for mig. Opgaver der på overfladen virker simple er altid overraskende besværlige fordi browserne opfører sig forskelligt, udviklingsmiljøerne har ikke haft god tool-support og det at manipulere DOM’en på en webside har altid krævet urimeligt meget kode.

Der er heldigvis sket en masse på den front det sidste stykke tid, hvor jeg tidligere har kigget på intellisence og debugging af javascript i VS2008 samt Microsofts ASP.NET Ajax framework. Nu jeg har ferie har jeg som opfølgning på dette givet mig til at lege lidt med nogle af de andre frameworks der findes, da det så småt er ved at være en lille jungle at finde rundt i. Heldigvis har det vist sig at være en jungle med mange forskellige blomster, og overraskende lidt ensartet vegetation – eller på almindelig dansk, de frameworks der er har en masse at tilbyde uden at der er en masse overlap i funktionalitet.

Jeg vil starte med lige kort at skrive lidt om javscript som sprog, da jeg har på fornemmelsen at der er mange der ligesom mig i lang tid aldrig rigtig fik taget mig tid til at finde ud af nogle af de grundlæggende ting omkring objekter og funktioner i javascript.

Lidt JavaScript basics, som du måske alligvel ikke ved

Ligesom mange andre har jeg i min karriere primært brugt javascript til simple ting, som validering og at vise alerts, popup vinduer osv. Jeg måtte derfor for lidt tid siden erkende at jeg egentlig vidste for lidt om hvordan sproget virkelig fungere, da min indlæring havde været meget drevet af tilfældighed ud fra hvad jeg lige havde haft af små problemer der skulle løses. Jeg brugte derfor lidt tid på at blive klogere og vil lige starte helt kort med nogle af de vigtigste ting jeg lærte dengang.
Som udvikler der er uddannet og hovedsageligt har arbejdet i et OO miljø, er javascript en underlig størrelse, da begreberne object og function forstås en del anderledes i javascript end i Java, C#, VB osv.

I OO sprog er en property på et object fast defineret i en klasse, og som kan tilgås via dot notation. I javascript er properties noget der tilknyttes dynamisk, og disse kan tilgås både via dot notation og via indexer syntaks. Det vil sige at i nedenstående kode vil de to nederste linier gøre præcis det samme. Den sidste måde at tilgå properties på dog giver mulighed for at bruge tegn der ellers er ugyldige i propertynavne som eksempelvis punktum og mellemrum.

var hund = new Object();
hund.Navn = "King";
hund['Navn'] = "King";

Det kan på overfladen virke smart at properties på den måde er dynamiske, men ”there is no such thing as a free lunch”. Problemet er selvfølgelig at en subtil stavefejl eller bare casingfejl vil bevirke at man tilknytter en ny property, og man derved ikke får sat værdien på den property man troede. Det er her prototyping kommer ind, da det giver os mulighed for at definere noget der minder om classes og properties samtidig med det giver mulighed for at bruge namespaces til at strukturere klasserne. Jeg vil dog vælge at springe let hen over det i denne omgang, da det er en større omgang at gå i dybden med og ikke hovedfokus for det jeg vil skrive om i det her indlæg.

Funktioner i javascript er som nævnt også meget anderledes i javscript, da funktioner er ”first class” koncepter. Det vil sige at disse opfattes som objekter og kan passes som argumenter til metoder og bruges som værdier på properties. Derfor vil de to nedenstående kodelinier betyde præcis det samme, da funktionen blot er et ”objekt” med et navn.

myFunc = function() {}
function myFunc {}

En anden vigtig forskel er brugen af this keywordet, der forstås anderledes end i andre sprog. I OO sprogene er this en reference en objektet hvorpå den kaldte metode findes, hvorimod det i javascript er en reference til det objekt der kalder funktionen. Man kan dog i javascript selv angive hvad this skal betyde ved at kalde en funktion igennem dennes .call eller .apply metode og passe en reference som første argument til det objekt man ønsker skal være this i den aktuelle kontekst.

var myCaller = new Object();
myFunc.call(myCaller);

JSON eller JavaScript Object Notation, er en anden måde at skabe objekter på i javascript, som er ved at vinde frem, da den kan være rarere at arbejde med i javascript, samtidig med det er et oplagt format til at serializere objekter i når de skal sendes imellem klienten og serveren og konverteres imellem javscript og dit OO language of choice. Jeg har skrevet om dette før men kort fortalt fungerer det ved at tuborg-klammer definerer et objekt, hårde klammer et array, kolon adskiller property navn og værdi, og elementer adskilles af komma.

var hunde = [
{Navn: ’King’, Fødselsdato:  new Date(2004,8,12)},
{Navn: ’Pluto’, Fødselsdato:  new Date(2006,6,10)}
 ];

JQuery – bliv gode venner med din DOM

Oprindeligt troede jeg egentlig bare at JQuery var en open source udgave af det scripting library der følger med til ASP.NET Ajax – en sammenligning jeg også har læst andre fremføre. Den sidste måned havde jeg imidlertid hørt nogle gode ting om det, så jeg ville lige kigge lidt nærmere på det. Efter at have læst og leget lidt med det, må jeg konkludere at det er meget lidt det har til fælles med ASP.NET Ajax, da det er nogle grundlæggende forskellige ting de to librarys søger at løse. ASP.NET Ajax er lavet med fokus på at give mulighed for at arbejde med et typesystem der minder mere om det der er i .NET, samtidig med at det understøtter udviklingen af Ajax Controls og Ajax Control Extenders. JQuery derimod har hovedfokus imod at det at arbejde med DOM’en på en html side, sådan at man på en præcis måde kan finde og modificere Dom elementer. Rigtigt nok er der overlap imellem ASP.NET Ajax og JQuery, da begge eksempelvis indeholder wrappere til at lave kald til webservices – men hovedfokus i de to er helt forskelligt.

JQuerys udgangspunkt er som navnet antyder at det giver mulighed for at ”query” elementer på en webside. Dette gøres meget naturligt igennem selectors ligesom man kender dem fra CSS. JQuery giver mulighed for at anvende et bredt udsnit af disse – og herunder flere end dem der reelt er standard i CSS i alle browsere i dag. Et helt basalt eksempel kunne være:

$(document).ready(function() {
$("div:odd").html("Woot"); 
});

Eksemplet viser et par forskellige ting som JQuery gør muligt. Den første linie kode viser brugen af et event som JQuery stiller til rådighed der bliver affyret når sidens elementer er hentet, men inden eksterne elementer som f.eks. billeder er læst helt ind. Det løser et problem man tit render på som er at hvis man skriver javscript i starten af en side, så kan man risikere at denne køres inden alle elementerne endnu er loaded, og omvendt hvis man bruger onload eventet ender man med at vente til alt er læst helt ind hvilket heller ikke altid er ønskværdigt. Den næste linie viser brugen af en selector der henter hvert andet (ulige) div element på siden, og sætter deres indhold til ”Woot”. Dette illustrerer hvor powerfull JQuery er, da man faktisk kan manipulere flere elementer i det der kaldes et wrapped set med meget lidt kode.

Udover at kunne manipulere eksisterende elementer vil man selvfølgelig også ofte gerne kunne tilføje nye elementer. Også her er det JQuery to the rescue, da det gør det meget enkelt.

$("<div>Totalt dynamisk indsat tekst der!<div/>").appendTo("#someParentDiv");

Her ses en af de andre mådet at bruge $ funktionen på, da den her fodres med noget html, som så udgør ens wrapped set. Derefter kaldes appendTo med en selector der finder de eksisterende elementer som der skal føjes til.
JQuery tilbyder en bred vifte af metoder til at arbejde med disse wrapped sets, manipulere elementer, properties, attributter osv. Fælles for dem alle er at de virker crossbrowser, hvilket er en af hovedpointerne i JQuery – nemlig at gøre det nemt og ensartet at skrive sine scripts. Udover almindelig element manipulation skal det nævnes at JQuery tilbyder funktioner til at lave animationer og effekter, wrapper funktioner til at foretage Ajax kald og det er bygget til at kunne extendes med plugins, som der allerede findes flere af.

En vigtig ting hvis JQuery skal bruges i samspil med andre javascript librarys er funktionen $ som også bruges af andre librarys. For at undgå denne konflikt kan man disable brugen af $ og i stedet tilgå funktionen direkte som ”jQuery”, hvilket $ i virkeligheden blot er en genvej til. For at disable $ skal man blot kalde jQuery.noConflict();

Har du fået lyst til at læse mere om JQuery kan jeg anbefale bogen JQuery in Action, som har været min primære inspirationskilde.

LINQ to JavaScript – endnu et skridt imod begrænsningen af for-loops

Navnet siger jo egentlig det hele, da de fleste efterhånden har hørt om og sikkert også leget lidt med LINQ. LINQ to JavaScript er helt enkelt et codeplex projekt, som implementere det der svarer til LINQ to objects i JavaScript. Fordelene ved LINQ er der allerede skrevet alt for meget om rundt omkring, så jeg vil gå lige på og fortælle lidt mere konkret om JavaScript implementationen.
Indtil videre er følgende operatorer implementeret, men der er med garanti flere på vej:

From, Where, Select, OrderBy, OrderByDescending, Count, Distinct, Any, All, Many, Reverse, First, Last, ElementAt, InterSect, DefaultIfEmpty, ElementAtOrDefault, FirstOrDefault og LastOrDefault.

Et eksempel på at bruge de mest gængse kunne være.

var myArray =  [
{Name:"Hans", Age:20 },
{Name:"Erik", Age:10 },
{Name:"Christian", Age:26 }
];

var myResult =
    From(myArray).
    Where(function(item){return item.Age > 15}).
    OrderBy("item.Name").Select(function(item){return item});

Som eksemplet viser kan operatorerne generelt tage to slags argumenter til at beskrive hvilken property der arbejdes på, idet man enten kan bruge en streng (eksempelvis ”item.Name”) eller en funktion der tager item som argument.
Jeg synes personligt at de er sluppet meget godt af sted med det der er implementeret i LINQ to JavaScript, og jeg er sikker på jeg selv nok skal komme til at bruge det en del fremover.
Ellers er der ikke mere jeg har tilbage at skrive om javascript og javascript frameworks for denne gang, men jeg håber det giver andre blod på tanden. Det i hvert fald har givet mig lyst til at arbejde mere med javascript efter at jeg har set hvad nogle af de her frameworks giver af muligheder.

Dynamic Language Runtime

by DotNetNerd 3. November 2007 23:36

DLR - Dynamic Language Runtime.

Jeg fik for et stykke tid siden øje på en blogpost der omhandlede endnu et tiltag Microsoft arbejder på til .NET frameworket - nemlig en Dynamic Language Runtime. Umiddelbart tænkte jeg "fint nok men hvad skal jeg bruge det til". Det spørgsmål fik jeg så besvaret nu her da jeg faldt over en video fra MIX07 omkring dette emne. Jeg vender tilbage til videoen senere, da den indeholdt et temmeligt fedt eksempel som jeg vil gengive.

Kort fortalt er styrken ved dynamiske sprog at de "bare er tekst" ligesom en aspx- eller xaml-fil. Derved giver de nogle muligheder for især webudviklere ved egentlig at vende en smule tilbage til webudviklingens barndom. Idet sprogene er fortolkede, og altså "bare tekst" der ikke skal kompileres for at kunne afvikles, kan man arbejde uden konstant at skulle igennem en code-compile-review cyklus.

Dette kan især være rart hvis man skal udgive rettelser til en webapplikation, men også under selve udviklingen da man kan sidde med browseren fremme på den ene skærm imens man retter i koden på den anden og ser ændringerne slå igennem med det samme.

Hvilke sprog kan man så kode i?

Til at at starte med arbejder Microsoft på at udvikle implementationer baseret på sprogene:

  • IronRuby
  • IronPython
  • JavaScript
  • Dynamic VB

Ligesom med den almindelige CLR er det meningen at det skal være muligt at udvide med flere sprog hen ad vejen. De 4 sprog der er med til at starte med er valgt ud fra at de for det første er meget udbredte, og så for JavaScripts vedkomne fordi det giver mulighed for at man meget let kan genanvende sine eksisterende Ajax scripts i f.eks en Silverlight applikation. VB er som altid representeret af hensyn til Microsofts eget Office team. IronRuby og IronPython er enormt populære sprog der er svære at komme uden om - og de har en force i at de begge har en lækker syntaks der er meget lidt verbos.

Mix and Match

Der før omtalte eksempel fra MIX07 synes jeg gav en virkelig god idé om hvilke muligheder der vil være for at lege "Mix and Match" i fremtiden, da det illustrerer hvor enkelt man kan blande forskellige sprog - hvad end det er CLR eller DLR sprog, og hvad enten det er ASP, Silverlight eller helt almindelig HTML.

Eksemplet er en Silverlight applikation skrevet i Ruby og benytter en knap skrevet i C#, som kører et animationsscript skrevet i DLR JavaScript der viser tekstelementer der floater rundt. Teksterne er hentet fra en service skrevet i VB, udfra et ord der er indtastet i en HTML textbox som tilgås via Silverlights HTML DOM.

require 'Silverlight.Samples.Controls.Version=0.0.0.0'

Controls = Silverlignt.Samples.Controls
Document = System.Windows.Browser.HtmlPage.Document

JS = require '3dText.js'
VB = require 'technorati.vbx'

def initialize(s, e)
    button = Controls.Button.new
    button.Text = "Click me"

    JS.initialize

    root.children.add button

    button.click do |s, e|
        JS.clearList
        term = Document.txtSearchTerm.Value
        items = VB.GetTitles(term)
        items.each { |item| JS.initializeName(item)}
        JS.playAnimation
    end
end

Som man kan se er Ruby meget letvægts, og hvis man tænker over antallet af komponenter skrevet i forskellige sprog fra forskellige miljøer der arbejder sammen her kan man ikke undgå at blive lidt imponeret over hvor smertefrit CLR og DLR sprog taler sammen.

Det er værd at bide mærke i de første 5 linier fra eksemplet hvor man ser hvor let det er at importerer komponenter fra serveren, samt at referere til dynamisk kode skrevet i andre sprog. Det er ganske enkelt bare at bruge en simpel require statement.

Derefter viser eksemplet en initialize metode, som det er defineret i den tilhørende XAML fil skal kaldes ved init. I initialize instantieres så en knap, og en tilsvarende initialize metode på JavaScript komponenten kaldes. Knappen tilføjes så til et canvas der er navngivet root. Knappen for derefter tildelt en anonym eventhandler, der clearer den liste af tekster og tilføjer nye ord hentet fra VB servicen. Til sidst er det blot at starte animationen og så er koden kørende.

Hvordan platformen blev til.

En sjov historie fra videoen er at en af dem der har været med til at lave det oprindeligt startede med at ville skrive en artikel for at lave grin med Microsoft, da han havde hørt at .NET var elendigt at bygge dynamiske sprog oven på.
Han skrev så en implementation af Python oven på CLR'en - og til hans store overraskelse sparkede den røv på den originale Python. Med andre ord viste benchmarks at hans implementation performede dobbelt så godt! Derefter endte han så med at arbejde for Microsoft og har været med til at bygge denne platform til at hoste dynamiske sprog.

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List