Functions
class: center, middle .title[ Front-end training # Functions Basics ] --- # Introduction 1. Function is a block of code 2. Functions should do only one "function" 3. JS functions can accept arguments, return a value or simply skip any of them ``` function meow() { // function body console.log('meow'); } // Call function meow(); function getName() { // function body return 'Petro'; } let name = getName(); console.log(name); ``` --- # Function features ### Function is an object. But also it can be invoked. ### Function can have name or be anonymous ### Function has a body ### Function object has some predefined properties and methods. ``` function outerFunction() { // The most common declaration // everything inside a { } brackets is a function body var innerFunction = function() { // Functional expression, function is anonymous // here is a body of inner function; } } outerFunction(); // we use () to invoke a function console.log(typeof outerFunction); // "function" - skip () to work with object console.log(outerFunction.name); // -> "outerFunction" console.log(outerFunction.toString()); // -> text of a function body ``` --- #Function is an object ### We can save function to variable ``` let myFunctionSaved = function myFunction() {...} ``` ### We can pass it as a parameter to another function ``` function a() {console.log("a was called");} function b(incomingFunction) { incomingFunction(); } // call function "b" and pass function "a" as an object to params b(a); // -> "a was called"; ``` ### We can return it from another function ``` function b() { return function a () { console.log(a.name + " was called"); } } var returnedFunction = b(); // call function "b" and receive a function object returnedFunction(); // -> "a was called"; ``` --- #Function scope basics ### 1. Scope is a hidden object, no direct access ### 2. Scope is a storage for all declared variables and functions ### 3. Function scope is created on each function call. ### 4. Function parameters become scope variables ``` function writeToScope(a, b) { // At the very start of a function a new function scope will be created by JS engine // like functionScope = new FunctionScope(); const c = {}; function innerFunction() { } // functionScope.a -> string 'a' // functionScope.b -> number 10 // functionScope.c -> object {} // functionScope.innerFunction -> function } // scope will be created only when function will be called writeToScope('a', 10); ``` --- #Function arguments ### Values we are passed on a function invocation are called parameters or arguments ### When a function is called and new scope is created - it has predefined property "arguments" ### Its a storage for the parameters which were passed on a function call; ``` function tryArguments(a, b) { // At the very start of function a new function scope will be created // functionScope = { // arguments: pseudo-array of passed parameters // } // all variable declarations become its properties console.log(a); // the same like arguments[0] console.log(b); // the same like arguments[1] // It's possible to get passed value even if you have not declared a param name console.log(arguments[2]); } tryArguments(1, 2, 3); ``` --- # Declaration, Expression, Self-invocation ### Declared function is just like a simple variable in the current scope (can be called anywhere in the current scope) ``` printParam('print me!'); function printParam(param) { console.log(param) } ``` ### Functional expression is a real variable (can be called only after variable gets the function object as a value) ``` let printParam = function (param) { console.log(param) } printParam('print me!'); ``` ### Self-invoked function is called only at the place it was decalred ``` (function(param) { console.log(param) })('print me!'); ``` --- # 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'; } ``` --- #Global context ### Our code is executed inside a global function ### For the global function its "scope" object it the same as "this" and is the "window" (or "global" for NodeJS) ``` // Somewhere in browser JS engine the function Global was called // Global() // It's scope object is a window object. But it also exposes "window" variable { // window: ... //} console.log(window === this); // -> true; console.log(window.window.window === this); // -> true; var x = 10; console.log(window.x === x); // -> true; console.log(window.x === this.x); // -> true; ``` --- # Hoisting Hoisting is a process of how variables appear in a function scope ### 1. "var", "let", "const" declarations go first ### 2. Function params go second and will overwrite params. ``` function tryHoisting(a) { // First: JS finds "var a" and hoists it declaration but it's value is undefined now. // Second: Function argument 'a' is written to functionScope.a -> string 'someText' - it's a param console.log(a); // -> writes "someText" to console var a = 10; // a is set to 10 instead of "someText"; // functionScope.a -> is number 10 now console.log(a); // -> writes 10 to console } tryHoisting('someText'); ``` --- # Hoisting ### 3. Functions declarations go third and will overwrite params and vars (but will conflict with let or const); ### 4. But setting value to var will overwrite a function object ``` // "var hoisted" was raised first, but then was overwritten by function named "hoisted" // typeof functionScope.hoisted -> "function" hoisted(); // -> a function was called console.log(hoisted); // -> Function body var hoisted = 10; // Now functionScope.hoisted = 10; typeof functionScope.hoisted -> "number" console.log(hoisted); // -> 10 function hoisted() { console.log("a function was called"); } ``` --- # Function arguments 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 ``` --- # Arrow functions (ES6) ### An arrow function expression has a shorter syntax than a function expression ### It's 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