's Picture

Kyle Simpson besöker Expressen

Postad av Jens Östlund

Förra veckan höll legendaren Kyle Simpson två heldagsworkshops för oss på Expressens utvecklingsavdelning. Kyle Simpson har länge figurerat i JavaScript-världen, men är mest känd för sin bokserie You Don't Know JS, som i sex delar går igenom JavaScript på djupet från grunden. Om du känner dig osäker på hur hur t. ex. this och prototype-kedjan fungerar, eller vad closures är för något så är det här du hittar svaren.

Det utmärkande med Kyle Simpson är att han är övertygad om vikten av att förstå de verktyg man använder sig av på djupet, och inte nöja sig med en ytlig, ungefärlig förståelse. Vi är ingenjörer och JavaScript är vårt huvudsakliga verktyg så vi måste förstå hur språket verkligen fungerar. Genom att plöja ECMAScript-specifikationen, samt otröttligt experimenterande har Kyle brutit ned JavaScript i sina beståndsdelar för att sedan bygga upp en sammanhängande bild av hur språket faktiskt fungerar. Det är frukterna av detta gedigna arbete som vi fick ta del av under våra 16 timmar med Kyle i form av passionerade föreläsningar och utmanande övningar.

Dag 1: Advanced JavaScript Foundations

Första dagen börjar Kyle med att börja från grunden och gå igenom hur JavaScript faktiskt kompileras och sedan tolkas. Detta fick vi lära oss genom att vi delades upp i par och rollspelade kompilator och scope-hanterare! Det kunde te sig ungefär såhär (exemplet är taget härifrån):

function foo(a) {
    console.log( a ); // 2
}

foo( 2 );

Engine: Hey Scope, I have an RHS reference for foo. Ever heard of it?
Scope: Why yes, I have. Compiler declared it just a second ago. He's a function. Here you go.
Engine: Great, thanks! OK, I'm executing foo.
Engine: Hey, Scope, I've got an LHS reference for a, ever heard of it?
Scope: Why yes, I have. Compiler declared it as a formal parameter to foo just recently. Here you go.
Engine: Helpful as always, Scope. Thanks again. Now, time to assign 2 to a.
Engine: Hey, Scope, sorry to bother you again. I need an RHS look-up for console. Ever heard of it?
Scope: No problem, Engine, this is what I do all day. Yes, I've got console. He's built-in. Here ya go.
Engine: Perfect. Looking up log(..). OK, great, it's a function.
Engine: Yo, Scope. Can you help me out with an RHS reference to a. I think I remember it, but just want to double-check.
Scope: You're right, Engine. Same guy, hasn't changed. Here ya go.
Engine: Cool. Passing the value of a, which is 2, into log(..).

På detta sätt byggde vi upp en intuition för hur JavaScript faktiskt exekveras, som sedan utgjorde basen för hans förklaringar av closures, modularisering, this-bindning, prototype-kedjan etc.

Dagen knöts ihop med en ingående förklaring av varför alla försök till klassbaserad objektorienterad JavaScript är dömda att misslyckas och att man istället bör använda sig av beteendedelegering, då det bättre följer hur JavaScripts prototypbaserade system fungerar.

Dag 2: Functional-Light JavaScript

Andra dagens tema var funktionell programmering i JavaScript med fokus på praktisk tillämpning utan att förlita sig på akademiska begrepp som funktorer, endofunktorer, monader etc.

Dagens påbud var följande:

  • Separera sidoeffekter från kärnlogiken. Sidoeffekter kan sammanfattas som antingen en funktion beror på något annat tillstånd i programmet än det vi explicit skickade in som argument, eller att en funktion påverkar programmet på annat vis än genom sitt returvärde.

  • Skapa rena funktioner. En ren funktion är en funktion vars anrop alltid kan ersättas med returvärdet från funktionen, dvs givet samma parametrar ska funktionen alltid returnera samma värde.

Med detta som grund gick vi igenom de koncept som utgör grundvalarna i funktionell programmering, så som funktionell komposition, currying, immutability (oföränderlighet), rekursion etc.

Om man ska reducera ned dagen så handlade den om att skriva kod som är deklarativ istället för imperativ. En imperativ lösning beskriver hur du löser något, medan en deklarativ lösning beskriver vad det du löser faktiskt är. Låt säga att du har en lista med objekt och du ska skapa en lista med alla namn:

var people = [
    { name: "Homer", id: 1 },
    { name: "Marge", id: 2 }
];

// imperativ lösning
var names = [];
for (var i = 0; i < people.length; i++) {
    names.push(people[i].name);
}

console.log(names); // ["Homer", "Marge"]

I den imperativa lösningen ovan löser vi problemet genom att skapa en tom lista och sedan använda en for-loop för att loopa över varje index i people och lägga till name-fältet för varje objekt i listan. Inte helt enkelt att beskriva i ord, men ett mönster så invant att jag inte tror många reflekterar över det. En deklarativ lösning skulle kunna se ut på följande sätt:

var people = [
    { name: "Homer", id: 1 },
    { name: "Marge", id: 2 }
];

// delarativ lösning
function getName(person) {
    return person.name;
}

var names = people.map(getName);

console.log(names); // ["Homer", "Marge"]

Här beskrivs names-listan som den listan vi får av att ta name-fältet för varje objekt i people-listan. Exemplet må vara väldigt enkelt, men tanken är att kod skriven på ett deklarativt sätt i slutändan blir mer läsbar, lättbegriplig och leder till färre buggar.

Kyle Simpson är en vältalig mästarpedagog med en sällsam förmåga att ta ett ämne och stegvis lära ut det från de mest lättbegripliga delarna till de mer svårtacklade. Vid dagens slut sitter man där utmattad efter en kavalkad av aha-upplevelser. Om du vill veta mer av det som berörts här i texten så bör du ta en titt i You Don't Know JS, eller i hans kommande bok Functional-Light JS.

PS. Missa inte vår nästa bloggpost, följ oss på Twitter!

Till startsidan