Functions
class: center, middle .title[ Front-end training # Functions Basics ] --- # Introduction Function is a "subprogram" that can be *called* by code external (or internal in the case of recursion) to the function. Like the program itself, a function is composed of a sequence of statements called the *function body*. Values can be *passed* to a function, and the function can *return* a value. © MDN --- # Declare function ### Function declaration ``` function myVeryUsefulFunction() { // function body console.log('meow'); } ``` ### Function expression ``` var myVeryUsefulFunction = function() { // function body console.log('meow'); }; ``` ### Function invocation ``` myVeryUsefulFunction(); // -> meow ``` --- # Anonymous function Function that has no name is called _anonymous_ function. Sometimes it is called _lambda-function_. ``` function() { console.log('hi'); } ``` --- # Declaration vs Expression In fact, function expression is just a creation of a variable setting its value to an unnamed function. Usefull for debugging purposes. ``` // we can access function's name through special syntax var noname = function(){}; console.log( noname.name ); // -> "" function hasname(){} console.log( hasname.name ); // -> "hasname" ``` Function declaration can be invoked above declaration itself: ``` aboveWeCall(); // -> 'yes we can' function aboveWeCall(){ console.log('yes we can'); } ``` Function expression throws an error in same situation: ``` aboveWeCall(); // -> Uncaught TypeError: aboveWeCall is not a function var aboveWeCall = function(){ console.log('no we can not'); } ``` --- # Function arguments Function can accept values as arguments to be used in their bodies. They behave just like regular variables. ``` function add(one, two) { console.log(one + two); } add(1, 2); // -> 3 ``` --- # Function arguments (cont.) In JavaScript quantity of function arguments is not strict: ``` // does not throw error for mismatched number of arguments add(1, 2, 3, 4, 5, 6, 7); // -> 3 add(); // -> NaN ``` Note: If you don't pass explicit value, then value of named argument becomes `undefined`: ``` function showArg(arg) { console.log(arg); } showArg(1); // -> 1 showArg(); // -> undefined ``` --- # Function arguments (cont.) Default values (ES6) Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed. ``` function showArg(arg = 'some default value') { console.log(arg); } showArg(1); // -> 1 showArg(); // -> some default value ``` --- # Function arguments object You may access all passed values with `arguments` keyword inside of a function. `arguments` is an array like object holding all of the values passed to the function ``` function showAllArguments() { // no named arguments console.log(arguments); console.log(arguments.length); } add(); // -> {} // -> 0 add(1, 2); // -> {'0': 1, '1': 2} // -> 2 ``` --- # Returning a value Function returns value with `return` keyword. ``` function greet(name) { var greetMessage = 'Hello, ' + name + '!'; return greetMessage; } console.log( greet('JS') ); // 'Hello, JS!' ``` You may use `return` anywhere in body, but it will stop execution of a function and jump out of it immediately. ``` function checkUser(login) { if (login == undefined) { return 'You did not specify a login'; } else if (login == 'admin') { return 'It is admin'; } else if (login == 'user') { return 'It is user'; } return 'User is unknown'; } ``` --- # Returning a value (cont.) If you don't specify `return` explicitly, JS will use `undefined` as a result of function call. ``` function noReturn() {} noReturn(); // -> undefined ``` --- # Functions are values In JavaScript, functions are values, that is why function expressions exist. ``` function multiplier(factor) { return function(number) { return number * factor; }; } var twice = multiplier(2); console.log( twice(5) ); // -> 10 ``` --- # Functions are values (cont.) You can pass function in other function. ``` function callPassedFunction(fn) { fn(); } function sayCalled() { console.log('called'); } callPassedFunction( sayCalled ); // -> 'called' ``` --- # Anonymous functions usage Often anonymous functions are used as values to other functions. E.g.: ``` callPassedFunction(function() { console.log('anonymous function called'); }); // -> 'anonymous function called' ``` Also, often, anonymous functions are created to be imediately invoked ``` (function() { console.log('called'); })(); // -> 'called' ``` --- # Scopes Scope is a block of code where variable can be accessed ("is visible"). In JavaScript scope is defined by function. ``` (function outer() { console.log(x) // -> undefined while ( !x ){ var x = 1; } console.log(x); // -> 1 inner(); // -> 1 function inner() { console.log(x); innerer(); function innerer(){ var x = 2; console.log(x); // -> 2 } } })(); ``` --- # Scopes (cont.) If you define variable without `var` keyword, it becomes __global__. ``` function createGlobalVariable() { x = 1; } console.log(x); // -> undefined createGlobalVariable(); console.log(x); // -> 1 ``` It is not recommended to use global variables. They lead to unclear code and may be a source of hard to find errors. --- # Scopes (cont.) To avoid variable names intersections usually self-executed anonymous functions are used: ``` (function() { var x = 1; console.log(x); })(); (function() { var x = 2; console.log(x); })(); ``` Both variables share same name, but are __different__ variables of different scopes. --- # Hoisting Behind the scenes, the __declaration__ of variable is __hoisted__ to the top. Because of hoisting it is recommended to define variables at the top of function, even if they are not used immediately there. ``` function countProfit(price) { var profit; if ( price >= 100){ profit = 10; } return profit; } ``` --- # Arrow functions (ES6) An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target. Arrow functions are always anonymous. ``` (param1, param2, …, paramN) => { statements } (param1, param2, …, paramN) => expression // equivalent to: (param1, param2, …, paramN) => { return expression; } // Parentheses are optional when there's only one parameter: (singleParam) => { statements } singleParam => { statements } // A function with no parameters requires parentheses: () => { statements } () => expression // equivalent to: () => { return expression; } let myVeryUsefulFunction = () => { console.log('meow'); }; ``` --- # Resources - http://eloquentjavascript.net/03_functions.html - http://code.tutsplus.com/tutorials/javascript-hoisting-explained--net-15092 - http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html