class: center, middle, lnu-background-yellow ### Grundläggande programmering (1DV021) # Föreläsning 3 --- class: lnu-background-cc ### Upphovsrätt för detta verk Detta verk är framtaget av Mats Loock i anslutning till kursen Grundläggande programmering (1DV021) vid Linnéuniversitetet. Allt innehåll i detta verk förutom fotografier, ikoner, bild på kurslitteraturen samt Linnéuniversitetets logotyp och symbol, är licensierad under en
Creative Commons Erkännande 4.0 Internationell Licens
. #### Du får använda detta verk så här - kopiera hela eller delar av innehållet - sprida hela eller delar av innehållet - visa hela eller delar av innehållet offentligt och digitalt - konvertera innehållet till annat format - du får även göra om innehållet Om du förändrar innehållet så ta inte med fotografier, ikoner, bild på kurslitteraturen samt Linnéuniversitetets logotyp och symbol i din nya version! Vid all användning måste du ange källan: ”Linnéuniversitetet – Grundläggande programmering (1DV021)” och en länk till https://coursepress.lnu.se/kurs/grundlaggande-programmering och till Creative Common-licensen här ovan. --- # Vad är funktioner bra för? - Alla språk har inbyggda funktioner som utför förutbestämda saker. ``` console.log('Hej hopp!') // skriver ut en sträng i konsolfönstret let result = Math.floor(3.14) // avrundar ett flyttal till närmasta lägre heltal ``` - Det finns dock inte funktioner för alla saker; du måste skriva egna. - Att dela upp ett program i mindre delar, __funktioner__, är viktigt för att... - ...strukturera kod. - ...få överblick över koden. - ...undvika att identisk kod upprepas.
Bryt aldrig mot principen __DRY__ _(__D__on't __R__epeat __Y__ourself!_).
- ...koden blir enklare att testa. --- # Att anropa en funktion ``` console.log('Hello, World!') // Skriver ut strängen (och returnerar värdet undefined). console.log() // Skriver ut en ny rad (och returnerar värdet undefined). let randomNumber = Math.random() // Returnerar ett värde från och med 0 till 1. ``` - En funktion anropas genom att ange dess namn följt av parenteser innehållande eventuella argument. - Argument är värden som skickas till funktionen. Det är funktionen som bestämmer om inget , ett eller flera argument tas om hand vid anrop. - Då en funktion exekverats klart returneras __alltid__ ett värde, ett så kallat returvärde. - Returvärde är det värde en funktion ger tillbaka. Bara ett värde kan returneras. - Parenteserna efter funktionens namn måste alltid anges vid anrop, oavsett om det finns argument eller inte. --- # Att definiera en funktion - Du definierar en funktion på ungefär samma sätt som en variabel, värdet är bara en funktion. ``` const sayHello = function (name) { let greeting = 'Hello, ' + name + '!' return greeting } console.log(sayHello('Ellen Nu')) // OUTPUT: Hello, Ellen Nu! ``` - En funktion är ett uttryck som börjar med nyckelordet `function`. - Mellan parenteserna kan ingen, en eller flera __parametrar__ finnas. - En parameter fungerar på samma sätt som en lokal variabel i funktionen. - Funktionens kropp, mellan klammerparenteserna, innehåller satserna som exekveras när funktionen anropas. - return-satsen, om den finns någon, bestämmer värdet funktionen returnerar då den anropas. Saknas `return`-sats returneras värdet `undefined`. --- # `return`-satser - En funktion behöver inte ha en `return`-sats. ``` const sayHello = function (name) { console.log('Hello, ' + name + '!') } sayHello('Nisse') // OUTPUT: Hello, Nisse! ``` - __OBS!__ Om en `return`-sats saknas i en funktion returnerar funktionen alltid värdet `undefined`! - Det kan finnas flera `return`-satser i en funktion. ``` const evenOrOdd = function (value) { // Är talet jämt delbart med 2? if (value % 2 === 0){ return 'jämt' } return 'udda' } let result = evenOrOdd(42) console.log('42 är ett ' + result + ' tal.') // OUTPUT: 42 är ett jämt tal. ``` --- # En generellt bättre lösning? - Funktion som returnerar en sträng (en mindre generell lösning). ``` const evenOrOdd = function (value) { // Är talet jämt delbart med 2? if (value % 2 === 0) { return 'jämt' } return 'udda' } let result = evenOrOdd(42) console.log('42 är ett' + result + 'tal.') // OUTPUT: 42 är ett jämt tal. ``` - Funktion som returnerar ett booleskt värde (en generellare lösning). ``` const isEven = function (value) { // Är talet jämt delbart med 2? return value % 2 === 0 }; let result = isEven(42) ? 'jämt' : 'udda' console.log('42 är ett ' + result + ' tal.') // OUTPUT: 42 är ett jämt tal. ``` --- # Parametrar och dess räckvidd ("_scope_") ``` const getFullName = function (firstName, lastName) { let fullName = firstName + ' ' + lastName // OBS! lokal variabel return fullName } let fullName = getFullName('Ellen', 'Nu') // OBS! synlig i aktuellt "scope" console.log('Personens fullständiga namn är ' + fullName + '.') // OUTPUT: Personens fullständiga namn är Ellen Nu. fullName = getFullName('Nisse', 'Hult') console.log('Personens fullständiga namn är ' + fullName + '.') // OUTPUT: Personens fullständiga namn är Nisse Hult. ``` - Parametrar fungerar i stort på samma sätt som lokala variabler i en funktion. - Variabler i en funktion måste definieras med `let`, eller `var`, för att bli lokala. - `firstName`, `lastName` och `fullName` är __lokala__ i funktionen `getFullName`. - Värdena parametrarna `firstName` och `lastName` tilldelas bestäms vid anropet av funktionen. --- # Mer om parametrar Javascript är generös vid tolkning av argument som skickas till en funktion. - Är det för många argument ignoreras de extra. ``` Math.floor(3.14, 9.36, 17.3) // → 3 ``` - Är det för få argument tilldelas funktionens parametrar värdet `undefined`. ``` const sumThreeNumbers = function (op1, op2, op3) { // Värden vid anrop enligt nedan: op1 = 23, op2 = 4, op3 = undefined let result = op1 + op2 + op3 // → NaN return result } console.log(sumThreeNumbers(23, 4)) // OUTPUT: NaN ``` - Lätt hänt att felaktigt antal argument skickas med vid anrop av en funktion. --- # Funktioner som värden - En funktion kan skickas som argument till en annan funktion. - En funktionsvariabels värde kan ändras (om den inte deklarerats med `const`). ``` let doNotLie = true; let confess = function (someFunction) { console.log(someFunction()) } let tellTheTruth = function () { return 'Mats är bäst!' } confess(tellTheTruth); // OUTPUT: Mats är bäst! if (doNotLie) { tellTheTruth = function () { return 'Mats är inte bättre än Johan!' } } confess(tellTheTruth) // OUTPUT: Mats är inte bättre än Johan! ``` --- # "_Closure_" - En funktion returnerar en nästlad funktion. - Funktionen som returneras har full tillgång till den omslutande funktionens lokala variabler. ``` let greet = function (greeting) { let localGreeting = greeting return function (name) { return localGreeting + ' ' + name + '.' } } let goodMorning = greet('God morgon') let goodEvening = greet('God kväll') console.log(goodMorning('Ellen')) // OUTPUT: God morgon Ellen. console.log(goodEvening('Nisse')) // OUTPUT: God kväll Nisse. console.log(goodMorning('Mats')) // OUTPUT: God morgon Mats. ``` --- # Olika sätt att skapa funktioner (1 av 2) ## Funktionsuttryck ``` greet() // ReferenceError: greet is not defined anotherGreet() // ReferenceError: anotherGreet is not defined // anonymt funktionsuttryck const greet = function () { console.log('Hello, World!') } // namngivet funktionsuttryck const anotherGreet = function sayHi() { console.log('Hello, World!') } greet() // OUTPUT: 'Hello, World!' anotherGreet() // OUTPUT: 'Hello, World!' ``` - Funktionen definieras först när satsen som definierar funktionen exekverats. --- # Olika sätt att skapa funktioner (2 av 2) ## Funktionsdeklaration ``` sayHello() // OUTPUT: 'Hello, World!' function sayHello() { console.log('Hello, World!') } sayHello() // OUTPUT: 'Hello, World!' ``` - Funktionen definieras precis innan omslutande funktion exekveras. ---