--- tags: ironhack, lecture, --- <style> .markdown-body img[src$=".png"] {background-color:transparent;} .alert-info.lecture, .alert-success.lecture, .alert-warning.lecture, .alert-danger.lecture { box-shadow:0 0 0 .5em rgba(64, 96, 85, 0.4); margin-top:20px;margin-bottom:20px; position:relative; ddisplay:none; } .alert-info.lecture:before, .alert-success.lecture:before, .alert-warning.lecture:before, .alert-danger.lecture:before { content:"👨‍🏫\A"; white-space:pre-line; display:block;margin-bottom:.5em; /*position:absolute; right:0; top:0; margin:3px;margin-right:7px;*/ } .skip { opacity:.4; } </style> ![logo_ironhack_blue 7](https://user-images.githubusercontent.com/23629340/40541063-a07a0a8a-601a-11e8-91b5-2f13e4e6b441.png) # JS | Functions ## Learning Goals After this unit, you will be able to: - Properly name, declare and invoke JavaScript functions. - Use parameters and arguments in your functions to enhance code reuse - Understand **callback** functions - Understand **anonymous** functions - Understand **the global** and **local or functional** scope - Return values from JavaScript functions - Understand **function declaration** and **function expression** - Understand what **arrow functions** are - Write functions using **good practices** - Understand some of the basics of the functional programming ## Hello, World! :::info lecture Si l'on doit exécuter plusieurs fois les mêmes instructions d'un programme, plutôt que de les répéter, nous allons pouvoir les définir dans une fonction, que nous pourrons ensuite appeler. => Les fonctions vont donc être pour nous un moyen de réutiliser du code à plusieurs endroits de notre programme. ::: Often we need to **perform a similar action in many places in our code**. For example, we need to calculate something on multiple places in our code. If we don't create a reusable piece of code, we will have to have the same code all over our scripts. That is super bad!!! But no need to worry - there are functions to save the deal. :::info Functions are the main “building blocks” of the program. They allow the code to be called many times without repetition. ::: --- Let’s start with a very basic example. We are going to create a function named `sayHelloWorld`, and all it will do for now is alert some text like `Hello, world!`. The [HelloWorld program](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program) was first coded in 1974 and it's typically the first program people create when learning a new language. There are [Hello World](http://helloworldcollection.de/) versions in almost every programming language!! ### Function Declaration :::info The **function declaration** is the process of **creating** a function, but not executing it. ::: :::info lecture Nous devons dans un 1er temps DÉFINIR notre fonction (et notamment **lui trouver un petit nom**) : ::: ```javascript // // Function Declaration // function sayHelloWorld() { const whatToSay = 'Hello, World!'; console.log(whatToSay); } ``` :::warning lecture Si l'on regarde en console, on ne voit aucun message. Déclarer une fonction ne l'exécute pas pour autant! ::: Please note that in the code above we are only creating the function. This tells the computer to **group all the statements inside the brackets, give it a name `{` ....`STATEMENTS` ... `}` and save it so we can call it later**, but it does not execute the code inside. ### Function Invocation :::info The process of executing (calling) the function is known as **function invocation**. ::: If we want the computer to execute those `STATEMENTS`, we need to call the function. How do we do that? Super Easy!! All we need to do is use the name we gave the function (in our case: `sayHelloWorld`) and add empty parenthesis after it: `sayHelloWorld()`. :::info lecture Pour ensuite pouvoir l'appeler (par son nom) : ::: ```javascript // Function Invocation sayHelloWorld(); // => Hello, World! sayHelloWorld(); // => Hello, World! sayHelloWorld(); // => Hello, World! ``` ## Function Syntax :::info lecture La syntaxe générale d'une fonction : ::: The Syntax to declare a [function](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Functions) is: ```javascript function <name> ([<argument_list>]) { <instructions> [return <expression>;] } ``` We are going to break it down a bit into each part, but before we do that, let's understand the symbols in the definition: :::info **Syntax symbols** - `function`: Reserved words and should be typed as it is. ie: `return` - `<something>`: User name. Angle brackets (`<`, `>`). ie: `myFunction` - `[something]`: Optional. Square brackets (`[`, `]`) ::: To summarize, when declaring a function we have to make sure these exist: - `function` keyword - the name of the function - parameters (if any, if not then just `()`) - body of the function - which is all the code between the curly braces `{}` :::info lecture Anatomie d'une fonction: ::: ```javascript // keyword function parameters (if any) // ^ name _____| // | | | function sayHelloWorld(){ // the code or so called the body of the function } ``` ### Function Name :::info lecture Comment nommer ses fonctions ? - les mêmes règles que pour les variables s'appliquent - on appelera souvent une fonction à l'aide d'un verbe: `sayHello`, `isEven`... - par convention, on utilisera pas de majuscule en 1ere lettre ::: - The name we define for each function. However, that doesn't mean we can use any word to name our functions. - The name should be very descriptive and should express what the function **does**. - As a rule of thumb, we will try to use **verbs** that describe **actions** (ex. getUsers, showErrorMessage, showSuccessMessage, etc.). - In JavaScript, we prefer to name functions the same as variables using the [camelCase](https://en.wikipedia.org/wiki/CamelCase) - `addTwoNumbers` - `sayHello` - Function name always begin with a lowercase letter: - `lowerCase` :thumbsup: - ~~`LowerCase`~~ ### Function Parameters and Function Arguments :::info lecture À l'appel de la fonction, nous allons pouvoir lui transmettre des valeurs. ::: In our previous example, we created a function to `sayHelloWorld`. That was cool because we could tell the computer to do the **exact same thing** over and over. :::info lecture Prenons cet ex: ::: Let's take a look at these examples. Imagine you want to say hello to your classmates. You could have a lot of functions like these: ```javascript function sayHelloMery() { console.log('Hello, Mery!'); } ``` ```javascript function sayHelloJohn() { console.log('Hello, John!'); } ``` ```javascript function sayHelloLucy() { console.log('Hello, Lucy!'); } ``` :::info lecture On comprend clairement qu'à part le nom, c'est pareil! ::: And then, we will have to call every function: ```javascript sayHelloMery(); // function will print: "Hello Mery!" sayHelloJohn(); // function will print: "Hello John!" sayHelloLucy(); // function will print: "Hello Lucy!" ``` Can you think of a different solution? Sometimes we may want to tell the computer to do very similar things, but not exactly the same each time. Here is when **parameters** come to rescue! For example, we may want to tell the computer to `sayHello` to different people each time. In this example, we could use the same function and pass to the function the `name` of the person we want to say hello to. :::info lecture On va donc pouvoir génériser notre fonction, en isolant ce qui d'une version à l'autre fait que nos fonctions sont différentes : on va en quelque sorte "factoriser" nos 3 fonctions en 1 seule : ::: ```javascript function sayHello(name) { console.log(`Hello ${name}!`); } ``` ```javascript sayHello('Mery'); // name = Mery // function will alert: "Hello Mery!" sayHello('John'); // name = John // function will alert: "Hello John!" sayHello('Lucy'); // name = Lucy // function will alert: "Hello Lucy!" ``` :::info lecture <span style="font-size:800%">😎</span> On a plus maintenant qu'une seule fonction `sayHello` qui accepte un paramètre `name`, dont on peut changer la valeur à l'appel de la fonction. ::: --- :::info lecture Et bien sûr, on est pas limité en nombre de paramètres. Il nous suffit de les séparer par des virgules. ::: We can have as many **parameters** in a function as we want. :::success **Parameter**: the variable name which is part of the function declaration. **Argument** is the value passed to function in the moment of its invocation. ::: :::warning lecture - Les paramètres sont comme des variables internes à la fonction. - <span style="font-size:180%;line-height:1.2;">Il n'auront de valeur, qu'**à l'appel de la fonction**.</span>: ```javascript sayHello('Mike'); sayHello('Bobby'); ``` => Expliquer le passage de la valeur dans le param au tableau véléda ☝️ On ne peut donc jamais voir dans une valeur dans une définition de fonction ! ::: ```javascript function sayHelloManyTimes(name, howManyTimes) { for (let i=0; i < howManyTimes; i++) { console.log(`Hello ${name}!`); } } sayHelloManyTimes('Michael', 2); // => Hello Michael! // => Hello Michael! sayHelloManyTimes(3, 'ERROR'); // Will this work? sayHelloManyTimes(2); // Will this work? sayHelloManyTimes('ironBrain'); // Will this work? ``` Cool huh? :) :::info lecture Les paramètres sont donc un moyen de transmettre des valeurs à notre fonction (lors de son appel); ::: ### Returning values :::info lecture Comme on l'a vu dans la syntaxe, une fonction peut retourner une valeur quand elle est appelée, grâce à l'opérateur `return` : ```javascript function <name> ([<argument_list>]) { <instructions> [return <expression>;] } ``` ::: :::info lecture Un exemple: ```javascript function double(nombre) { return nombre * 2; } ``` ::: :::warning lecture - Si pas de `return` => la fonction retourne `undefined`: ```javascript var result = sayHello(); console.log(result); // undefined ``` ou `return;` tout court : ![](https://i.imgur.com/t71oZ02.png =x150) - `return` arrêtre la fonction : les instructions se trouvant après un `return` dans la fonction ne seront pas exécutées ```javascript function cool() { return "c'est cool"; console.log("😭"); // pas exécuté! } ``` ::: Functions help us bundle different instructions together, and we can also add parameters to the function so that its behavior will change depending on those parameters. Functions also have an interesting property; they **return a value**. It is not mandatory to explicitly return a value in a function, but it is strongly recommended that you do so when it makes sense. Why return a value? Because we can later use that returned value inside an expression, assign it to a variable, etc. :::info *Potential interview question:* A JavaScript function **always returns something**. When a returning value is not specified, the function returns `undefined`. ::: We already covered [undefined](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/undefined) as primitive data type but here you can refresh your knowledge. Example 1: ```javascript function printName(name){ return name; } printName("Ana"); // console: // Ana ``` Example 2: ```javascript function calculateTotalPrice(price, taxPercent){ if(typeof price !== 'number' || typeof taxPercent !== 'number'){ return `You have to pass number values!`; } const theTaxPart = price * taxPercent / 100 return `${price + theTaxPart} €`; } calculateTotalPrice(5, 7); // <== 5.35 € ``` As you can see, **one function can have more one return statement**. In the previous example, we took care of the edge case if user passed the string or some other type of value and if that would be the case we would return a message to user. This leads us to one more conclusion: **there's nothing after return, that is the last statement in the function**. If the user passed a string instead of a number, they would get the message, and the rest of the code would never execute. #### Return a function <div class="skip"> We can also return another `function`, let´s see an example: ```javascript function anotherFunction(text){ console.log(`Hello ${text}!`); } function oneFunction(name) { return anotherFunction(name); } oneFunction("Lluis"); // Prints "Hello Lluis" ``` </div> #### Random Example We already covered [Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) method and here we will play a bit with it and try to apply it in the function. `Math.random()` returns a floating-point, pseudo-random number in the range `[0, 1)` that is, from 0 (inclusive) up to but not including 1 (exclusive). ```javascript var zeroToOne = Math.random(); // Random integer number [0,1] // Returns a random number between min (inclusive) and max (exclusive) function getRandomArbitrary(min, max) { return Math.random() * (max - min) + min; } ``` The example above was very simple and had only one instruction. However, we can have many instructions inside one function: ```javascript function gradeTheStudent () { const grades = ['Master', 'Good', 'Acceptable', 'Average', 'Poor', 'Fail']; let randomNumber = Math.random(); // Random decimal [0.0 - 1.0) randomNumber = randomNumber * grades.length; // Random decimal [0.0 - 6.0) randomNumber = Math.floor(randomNumber); // Random integer [0 - 5] return grades[randomNumber]; } const myGrade = gradeTheStudent(); console.log(myGrade); ``` We will be talking more about `arrays` very soon but we assume you remember basics from your prework. If you need a short reminder, you can sneak peak to the official [MDN Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) docs. ### JavaScript Callback Functions When we pass an argument to the `function`, we can pass any variable type we know, even **other functions** 😱 They are know as **callback functions**. :::info A callback function is a function that is passed to another function as a parameter and will be executed **after** another function is finished executing, and that's where the name cames from - "call back". ::: :::info lecture Lors d'un appel de fonction, on va également pouvoir passer des fonctions en paramètre : <span style="font-size:800%">😱</span> Par exemple: ```javascript wesh(["Marcelle", "John", "Helena"], sayHello); // ^ // on passe notre fonction // ``` ```javascript function wesh(names, speak) { for (let i = 0; i < names.length; i++) { speak(names[i]); } } ``` --- A quoi cela peut-il servir ? Par ex, on changeant simplement la valeur du 2e param par une autre fonction, on peut maintenant dire "au revoir" ```javascript wesh(["Marcelle", "John", "Helena"], sayGoodbye); ``` ::: :::info lecture Une fonction passée en paramètre sera appelée : **fonction de callback** ::: Now there can be a question - why would we pass a function as a parameter to the other function? Let's create an example: ```javascript function eatDinner(){ console.log("Eating the dinner 🍽"); } function eatDessert(){ console.log("Eating the dessert 🍰"); } eatDinner(); // <== Eating the dinner 🍽 eatDessert(); // <== Eating the dessert 🍰 ``` Great, one function executed and then another so we got the dinner first and then we got the dessert. But, you know, sometimes the dinner prep can take a reaallllly long time and then if we don't handle the situation properly, we could be in the situation to get the dessert before the dinner is even served. (Which is not that bad especially if they serve Tiramisu 🥳) We will simulate this situation just delaying the execution od `eatDinner()` function for a couple of seconds using the `setTimeout()` function. We will use setTimeout much later; now we need it just to show what would happen if one of the functions didn't execute on time. ```javascript function eatDinner(){ setTimeout(function(){ console.log("Eating the dinner 🍽"); }, 1000) } function eatDessert(){ console.log("Eating the dessert 🍰"); } eatDinner(); eatDessert(); // the console: // Eating the dessert 🍰 // Eating the dinner 🍽 ``` As we can see, we called first `eatDinner()` function and then `eatDessert()` but in the console, the first conole.log is from the second function. This means that JavaScript didn't wait for the response from the first function, but instead, it moved to the second and then after 1000 milliseconds (that's the delay we passed to the *setTimeout*) it executed the first function. This kind of situations are very often, and you will deal with them especially in the module 2 and 3 when working with some API requests (you will know everything about this, just patience 🙏🏻). Imagine situation where you need a lot of data from some API and then to load the page with that data displayed - if it takes a bit longer time to get the data, and you don't handle this situation using callbacks or some other approach, you will end up displaying an empty page to users since the page will load before the delayed data arrives. Do you understand now a bit better why we need callbacks? Yes, correct! :::success The callbacks are the way to make sure that some piece of code doesn't execute before some other code hasn't finished executing. ::: Now let's use the knowledge we just got and make sure we get that dinner before the dessert comes. ```javascript function eatDinner(callback){ console.log("Eating the dinner 🍽"); callback(); } function eatDessert(){ console.log("Eating the dessert 🍰"); } eatDinner(eatDessert); // <== notice that there's NO () when passing a function as argument here // Eating the dinner 🍽 // Eating the dessert 🍰 ``` :pencil: **Time to practice** Play around with the example below and try to understand it: ```javascript function functionOne(x) { console.log(x); } function functionTwo(var1, var2) { var2(var1); } functionTwo(2, functionOne); ``` *What is printed in the console and why?* ### Anonymous functions :::info lecture Une fonction est dite "anonyme" si elle n'a pas de nom. Ex: ```javascript ["la", "lala", "laaa"].forEach(function (parole) { console.log(parole); }); ``` C'est ici le cas de : ```javascript function (parole) { console.log(parole); } ``` passée en paramètre de `.forEach()` --- En fait, on pourrait lui donner un nom si on la déclarait avant : ```javascript function chante(parole) { console.log(parole); } ["la", "lala", "laaa"].forEach(chante); ``` mais puisqu'on lui passe directement, pas besoin de nom. -- NB : En conséquence, une fonction anonyme ne sera pas réutilisable ailleurs qu'où elle est définie ::: :::info An anonymous function is a function that was declared without any named identifier to refer to it. ::: We actually already used an anonymous function in one of the snippets above with `setTimeout()`: ```javascript setTimeout(function(){ console.log("This is just an example of anonymous function since this function really doesn't have a name.") }, 1000); ``` If we, for some reason, need to name this function, that could look like this: ```javascript function someFunctionName(){ console.log("This is just an example of anonymous function since this function really doesn't have a name.") } setTimeout(someFunctionName, 1000); ``` But if we never again will use this function (`someFunctionName()`) there's no need to name it really. :+1: An anonymous function is usually not accessible after its initial creation unless we assign it to a variable and keep a reference to it, like in this example: ```javascript const anon = function(){ console.log("An0nym0us Funct10n"); } anon(); // An0nym0us Funct10n ``` To summarize: :::info lecture Une fonction anonyme est particulièrement indiquée avec `setTimeout`, qd on se fiche de réutiliser la fonction ailleurs : ```javascript setTimout(function () { console.log('je serai affichée dans 1s'); }, 1000) ``` ::: :::info :bulb: Anonymous functions also help us avoid naming things that don't necessarily need a name. ::: Anonymous functions can be used as a parameter passed to another function. ```javascript function doSomethingWithAFunction(name, functionToCall){ functionToCall(name); } // Anonymous Function doSomethingWithAFunction("Ironhacker", function(someParameter){ console.log(`Hello ${someParameter}.`); }); // => Hello Ironhacker. // Anonymous Function doSomethingWithAFunction("Ironhacker", function(someParameter){ console.log(`Goodbye ${someParameter}.`); }); // => Goodbye Ironhacker. // Anonymous Function doSomethingWithAFunction(2, function(someParameter){ console.log(2 + someParameter); }); // => 4 ``` It's important to become familiar with anonymous functions. We will use them during this course, but for now, it's enough for you to know that they exist 😉 ### Practice Abstraction <div class="skip"> Let´s imagine we are creating our own **Math Quiz Game**. For our game, we need to generate some quizzes, and it must be a way to do it randomly with JavaScript code. All the quizzes are sums and should be adding 2 numbers between 0 and 100. ```javascript const newQuizz = Math.floor(Math.random()*101) + "+" + Math.floor(Math.random()*101); console.log(newQuizz); //We should get `a randomNumber`+ `a randomNumber` ``` Great, we have our quiz! ☝️ But we have a problem! This is a game, so we will need to make a lot more quizzes, right? And our code just runs it just once. If we want to do it again, we need to type it out all over again. Instead, we can isolate the random number generator, and the quiz generator, into functions. ```javascript //with a function, we can event set different limit each time we call the function function getRandomNumber(limit){ return Math.floor(Math.random()*(limit+1)); } function makeAQuizz(limit){ const generateQuizz = getRandomNumber(limit) + "+" + getRandomNumber(limit); return generateQuizz; } newQuizz = makeAQuizz(100); newQuizz = makeAQuizz(200); newQuizz = makeAQuizz(300); // Now we can create as many quizzes as we want, and change the limit as many times as we want! ``` </div> ## Functions and variable declarations - matter of scope :::info lecture La portée d'une variable ou scope, est la "distance" jusqu'où la variable existe. - Ai-je accès à une variblae déclarée à l'intérieur d'une fonction ? ![](https://i.imgur.com/mAvHWdA.png) - Ai-je dans le corps d'une fonction, accès à une variable définie à l'extérieur ? ![](https://i.imgur.com/jG2igrg.png) - Puis-je déclarer depuis une fonction, une variable déjà déclarée à l'extérieur ? ![](https://i.imgur.com/cPIkrjL.png) - quel est la portée des arguments ? ![](https://i.imgur.com/nxh7MHy.png) - Est-il possible de déclarer une variable du meme nom qu'un parametre ? ![](https://i.imgur.com/UkxUwIu.png) --- - Un scope est comme un mur qui enferme les variables. Les variables déclaré à l'intérieur, n'existe plus à l'extérieur. Par contre, elle existe partout à l'intérieur, meme si d'autres murs. ![](https://i.imgur.com/o904Hc7.png =x100) ![](https://docs.google.com/drawings/d/e/2PACX-1vRFru8jH26Wga3TLkxFF0GSDRFSdAGPqgM4j3UIYk7WC_5AXKZsYD9tgzkdfXaolSCPxIAg0flUfqSG/pub?w=851&h=790 =x300) - 2 scopes possibles : functional / block - **functional**: Une `function` définit un scope, à l'intérieur duquel les variables (`var`, `let`, `const`) ne peuvent remonter. ```javascript function sensDeLaVie() { // functional scope var reponse = 42; … } console.log(reponse); // undefined ``` - **block**: Les accolades `{}` définissent un scope, à l'intérieur duquel les variables (`let`, `const`) ne peuvent remonter. ```javascript if (age > 21) { // block scope let msg = ""; } console.log(reponse); // undefined ``` NB : a fortiori, les variables `let` et `const` ne peuvent pas remonter une `function`. - **implied global**: Si l'on oublie de déclarer une variable, celle-ci devient globale (attachée à `window`) ```javascript function toto() { i = 4; } toto(); console.log(boo); // 😱 4 ``` --- A votre avis: ```javascript var toto = 4; function foo() { var tata = 6; toto += tata; // ?? if (true) { var titi = 2; console.log(toto + tata + titi) // ?? } console.log(titi) // ?? } foo(); console.log(toto); // ?? console.log(tata); // ?? ``` ::: Here we will touch a matter of **scope** in JavaScript. :::info A scope is a context in which a function or a variable is visible or can be referenced from different parts of code. ::: The matter of scope is pretty complex, and we have to be careful when introducing this concept so for now, let's just talk about **global** and **local/functional** scope. ### Local scope :::warning A variable declared inside the function is scoped to that function, meaning it's not possible to access it (use it) outside the function. ::: Let's see the example: ```javascript function sayHello() { let firstName = "Ana"; // <== local variable console.log(`Hello ${firstName}!`); } sayHello(); // <== Hello Ana! console.log(firstName); // <== ReferenceError: firstName is not defined ``` ### Global Scope :::info If a variable is declared outside of the function, it is possible to use it in and outside of the function. ::: ```javascript const firstName = "Ana"; // <== global variable function sayHello() { console.log(`Hello ${firstName}!`); } sayHello(); // <== Hello Ana! console.log(firstName); // <== Ana ``` :warning: It is also possible to **modify** variables defined in the outter scope in the function. ```javascript let firstName = "Ana"; // <== global variable function sayHello() { firstName = "Martina"; console.log(`Hello ${firstName}!`); } console.log(`Before the function executes the first name is ${firstName}.`); // <== Before the function executes the first name is Ana. sayHello(); // <== Hello Martina! console.log(`After the function executes the first name is ${firstName}.`); // <== After the function executes the first name is Martina. ``` However, since these are the two separate scopes, it is possible to declare the same named variables in both scopes. This is known as **variable shaddowing**. When it comes to *variable shadowing*, the function will use the variable declared locally (in the function): ```javascript let firstName = "Ana"; // <== global variable function sayHello() { let firstName = "Martina"; // <== local variable with the same name as the global one console.log(`Hello ${firstName}!`); } console.log(`Before the function executes the first name is ${firstName}.`); // <== Before the function executes the first name is Ana. sayHello(); // <== Hello Martina! console.log(`After the function executes the first name is ${firstName}.`); // <== After the function executes the first name is Ana. ``` To make a final conclusion: :::info Global variables are accessible from any function unless they are shaddowed by local variables (locally created variables with the same name). ::: ## Function Expression :::info lecture Une fonction peut aussi être déclarée grâce à une variable + une fonction anonyme: ```javascript let sensDeLaVie = function () { return 42; }; ``` ce qui revient au même que dans cette fonction nommée : ```javascript function sensDeLaVie() { return 42; } ``` ::: So far we talked about **function declaration** which has this format: ```javascript // having parameters // is optional // | function someName(someParameters){ // some code here } ``` But we also saw in one of the previous examples something like this: ```javascript let someName = function(){ // some code here } ``` Now, we will explain the difference: - the first code snippet is **function declaration** - the second code snippet is **function expression** What is the difference you might ask now? Well besides the obvious **difference in syntax**, the more important difference is **when the function is actually created** by the JavaScript engine that executes the code. :::info - Function Expression is created in a moment when the execution reaches to that point in the code, and it can be used from that point on - Function Declaration is created at the very beginning when the script starts the execution which means that this kind of functions can be used even before then they are created in the code ::: Let's see the example and it should be easier to understand: ```javascript // Function Expression greeting("Ana"); // TypeError: greeting is not a function let greeting = function(name) { console.log(`Hello, ${name}`); } ``` So using `Function Expression` we **can't call a function before it is initialized**. ```javascript greeting("Ana"); // Hello Ana function greeting(name) { console.log(`Hello, ${name}`); } ``` So using `Function Declaration` we **can call a function before it is initialized**. :warning: However, like for almost every rule, there's an exception: **if function declaration is inside some block scope (this is a new thing for you, but for now think of it like it is a local scope), it's not reachable for the outside**. Let's see: ```javascript let name = prompt("What is your name?"); if (name){ function greeting(name) { console.log(`Hello, ${name}`); } greeting(name); // <== Hello nameYouEntered } greeting(name); // <== ReferenceError: greeting is not defined ``` In the previous example, `greetings()` lives inside the scope of the `if` statement, so it's reachable only in there. Outside, it doesn't exist. Can we make it available outside? Yes. We could turn it into **function expression** and declare a variable in the outer scope, outside of the `if` statement. ```javascript let name = prompt("What is your name?"); let greeting; if (name){ greeting = function(name) { console.log(`Hello, ${name}`); } greeting(name); // <== Hello, nameYouEntered } greeting(name); // <== Hello, nameYouEntered ``` The error is gone 🏆 Next question you might have - when to use function declaration and when to go for function declaration? :::info :thumbsup: As a rule of thumb, when creating the function, the **first choice should be function declaration** since it gives more freedom and you can use it, if needed, even before it's declared. But, if for some reason, using function declaration doesn't serve you well, then go ahead and use function expression. ::: ## Arrow functions :::info lecture ES6 syntaxic sugar: ```javascript function power(nombre, puissance) { return nombre ** puissance; } ``` équivalent à: ```javascript let power = (nombre, puissance) => { return nombre ** puissance; } ``` ::: :::info lecture Super pouvoirs: - si 1 seul paramètre => parenthèses optionnelles: ```javascript let carre = nombre => { return nombre ** 2; } ``` - si une seule instruction => pas d'accolade `{}` + `return` implicite ```javascript let power = (nombre, puissance) => nombre ** puissance; ``` ::: One of the updates of ES6 was introducing a simpler syntax for creating the functions. This way reminds a lot of function expression and it's called arrow functions. Let's reuse one of the examples from before: ```javascript // function expression: let greeting = function(name) { console.log(`Hello, ${name}`); } // arrow function: let greeting = name => { return name; } ``` As we can see, the keyword `function` is skipped, the parameter doesn't have braces around (although this changes when we have more than one parameter) and there's `=>` arrow between the parameter and the body (`{...}`) of the function. But this function can, even more, be shortened - since we return only one expression (there's only one line of code in the body), we can **omit the braces and skip the return** since it's implicit: ```javascript let greeting = name => name; greeting("Ana"); // <== Ana ``` So much cleaner and shorter! In case **there are no parameters passed then empty parentheses are mandatory**: ```javascript let greeting = () => console.log("Hello there!"); ``` As a conclusion: :::info If the right side is only a one-line expression, we can omit the curly braces and return statement is omitted as well. However, if we need to write multiline statements in the function, then we can do it using the curly braces `{...}` and using mandatory `return` statement. ::: ## Writing Good Functions Functions are one of the pillars of programming. Functions help us to keep our code clean and well organized, and as we write more and more code. * **[Reuse code](https://en.wikipedia.org/wiki/Code_reuse)**: We can call a function as many times as we need it in our code, but we only need to define how it works once :) * **[Abstraction](https://en.wikipedia.org/wiki/Abstraction_(software_engineering))** is a technique that allows us to think at higher, more *abstract* levels. * Ie. if we know **what** `Math.floor()` does, we can use it happily in our code... we don't have to worry about **how** math.floor() performs it's magic. It's abstracted from us * **[Separation of Concerns](https://en.wikipedia.org/wiki/Separation_of_concerns)**: Functions allow us to separate a big problem into many smaller ones. * **[Single Responsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle)**: A function has to do just one thing, and the name of the function has to be very clear so you can identify what is doing just reading the name. ### Code reuse and division of responsibilities From generalization, code reuse arises in a natural way: now we can perform the same operation on different places without repeating a single line of code. We are reusing the function. Division of responsibilities refers to the level of isolation. **One function should only do one thing**. It sounds simple, but mastering the division of responsibilities is not that easy. Here are some tips: * Name your functions with verbs, but only **one verb** per function. * Making a decision is _one thing_ to do * If your function is more than 20 lines of code, you're probably doing it wrong. * If you're grouping bunches of instructions, you're probably doing more than one thing. ### Refactoring :::success [Code Refactoring](https://en.wikipedia.org/wiki/Code_refactoring) is a technique in software development by which we change the way the code is structured, keeping the same functionality. ::: It is a good practice to refactor our code often, as it will help us to make it better, more modular, and easier to maintain. Examples of [refactoring techniques](https://en.wikipedia.org/wiki/Code_refactoring#List_of_refactoring_techniques) may include techniques such as: - Choosing better names for variables, functions, etc. - Taking pieces of functionality and abstracting them in separate functions Let's look at our `avg()` function: ```javascript function avg(array) { if (array.length === 0 ) { return; } for (let sum=0, i=0; i < array.length; i++) { sum += array[i]; } return sum/array.length; } ``` If we think about it, it actually does two separate things: 1. It calculates the sum of all the items in the array 1. It divides them by the length of the array We can further improve this by isolating one of those calculations into a separate function. We need to break down the code so that it does the same thing, but it's easier to understand. Let’s call the first step `sum()` and make it into it's a separate function. Then the `avg()` could be rewritten, now using our `sum` function: ```javascript function sum(array) { for (let sum=0, i=0; i < array.length; i++) { sum += array[i]; } return sum; } function avg(array) { if (array.length === 0) { return; } return sum(array) / array.length; } ``` As you can see, we are calling the function`sum()` as part of the expression for the `return` statement of the `avg()` function. Cool, right? ## Bonus: Recursion :::info lecture Voir mémo : https://hackmd.io/@abernier/HJXbh_BVE?type=view ::: ![](https://i.imgur.com/hUuqNCH.png) Some function definitions are implemented in a way they use their own definition. It’s like function inception. For instance, a factorial function is defined as factorial of `n` is `n` times the factorial of `n - 1`, except for factorial of `0`, which is `1`. Therefore, we can write this as: ```javascript function factorial(number) { if (number === 0) { return 1; } return number * factorial(number - 1); } factorial(4); // 4 * factorial(3) // 4 * 3 * factorial(2) // 4 * 3 * 2 * factorial(1) // 4 * 3 * 2 * 1 * factorial(0) // factorial of 0 is 1 :) // 4 * 3 * 2 * 1 * 1 // 4 * 3 * 2 * 1 // 4 * 3 * 2 // 4 * 6 // => 24 ``` ## Functional Programming Functional Programming (FP) is a programming paradigm based on the following principles: - using `pure functions` - avoiding data mutation and - avoiding side-effects. Let's now see what this means. **Pure function** is a function which: - given the same inputs always returns the same outputs - has no side-effects. If you want to read more, you can start [here](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976). **Immutability** is one of the core concepts of functional programming. Basically means that once it's created, value can't be modified. Here please remember: immutable doesn't mean creating a variable with `const`. `const` creates a variable that can't be reassigned after it's created. Creating a variable using *const* doesn't make it immutable. **Side-effect** that needs to be avoided is modifying any external variable, ex. a variable declared in the global scope. There are more side effects, and you can read more about it [here](https://dzone.com/articles/side-effects-1). FP has the following (non-exhaustive) features: - **First-Class Functions:** which means you can treat a function as any other piece of data: assign it to variable, pass it to the other functions, return them from functions, etc. ```javascript var add = function (a, b) { return a + b; }; add(2, 3) // => 5 ``` - **High-Order Functions:** are any functions that can return functions or receive other functions as parameters. ```javascript var add = function (a) { return function (b) { return a + b; }; }; var add2 = add(2); add2(3); // => 5 add(4)(5); // => 9 ``` Functional programming is a **declarative paradigm**, meaning that the program logic is expressed without explicitly describing the flow control, but rather expressing **what needs to be done**. **Imperative** programming is more descriptive - describes the steps that need to be taken to achieve results. This kind of programming is more focused on **how to do things**. To summarize this short intro to functional programming: :::info FP prefers - pure functions over side-effects - immutability over mutating data - reusable code based on high-order functions - declarative over the imperative approach ::: ## Summary In this lesson, you learned how to declare and call functions in JavaScript. Also, you learned what are and how to use parameters and arguments; you get familiar with returning values. You understand and know how to use local and global scope. You got familiar with the rules of writing clean code and refactoring, code reuse, and division of responsibilities. Now you know what is a recursion, although this is a broad term so check the Extra resources if you want to learn more. In the very end, you got familiar with the basics of functional programming. ## Extra Resources - [Functions - Mozilla Developer Network](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Functions) - [Callback functions](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) - [Learn and Understand Recursion in JavaScript](https://codeburst.io/learn-and-understand-recursion-in-javascript-b588218e87ea) - [A beginner friendly intro to functional programming](https://codeburst.io/a-beginner-friendly-intro-to-functional-programming-4f69aa109569)