ES6 - Functions
ES6 - Functions
Section titled “ES6 - Functions”Functions are fundamental building blocks in JavaScript, allowing you to encapsulate a block of code that can be executed multiple times. ES6 (ECMAScript 2015) and subsequent versions introduced several powerful enhancements to function syntax and capabilities.
Defining Functions
Section titled “Defining Functions”1. Function Declaration:
Section titled “1. Function Declaration:”Hoisted to the top of their scope, meaning they can be called before they are defined in the code.
function greet(name) { console.log(`Hello, ${name}!`);}greet("World"); // Output: Hello, World!2. Function Expression:
Section titled “2. Function Expression:”Assigned to a variable. Not hoisted; can only be called after the assignment.
const add = function(a, b) { return a + b;};console.log(add(5, 3)); // Output: 8Arrow Functions (ES6)
Section titled “Arrow Functions (ES6)”Arrow functions provide a more concise syntax for writing function expressions and have a significant difference in how this is handled: they lexically bind this, meaning this inside an arrow function refers to the this value of its surrounding (enclosing) lexical scope. They are not suitable for all situations (e.g., object methods that need their own this, or as constructors).
Syntax Variations:
Section titled “Syntax Variations:”- Basic:
(param1, param2) => { statements } - Single parameter (parentheses optional):
param => { statements } - No parameters:
() => { statements } - Single expression (implicit return, braces and
returnkeyword omitted):(param1, param2) => expression
Example: Arrow Functions
Section titled “Example: Arrow Functions”const multiply = (x, y) => x * y;console.log(multiply(4, 5)); // Output: 20
const square = num => num * num;console.log(square(7)); // Output: 49
const sayHi = () => console.log("Hi there!");sayHi(); // Output: Hi there!
const numbers = [1, 2, 3, 4];const doubled = numbers.map(n => n * 2);console.log(doubled); // Output: [2, 4, 6, 8]Lexical this in Arrow Functions:
Section titled “Lexical this in Arrow Functions:”function Timer() { this.seconds = 0; // In traditional function, 'this' inside setInterval would be global or undefined (strict mode) // setInterval(function() { // this.seconds++; // 'this' is not Timer instance here // console.log(this.seconds); // }, 1000);
// Arrow function inherits 'this' from Timer constructor scope setInterval(() => { this.seconds++; console.log(`Timer (lexical this): ${this.seconds}`); }, 1000);}// const myTimer = new Timer(); // Uncomment to run this example in a browser/Node environmentDefault Parameter Values (ES6)
Section titled “Default Parameter Values (ES6)”You can specify default values for function parameters. If an argument for that parameter is not provided or is undefined, the default value is used.
Example: Default Parameters
Section titled “Example: Default Parameters”function greetUser(name = "Guest", message = "Welcome") { console.log(`${message}, ${name}!`);}greetUser(); // Output: Welcome, Guest!greetUser("Alice"); // Output: Welcome, Alice!greetUser("Bob", "Good morning"); // Output: Good morning, Bob!Rest Parameters (ES6)
Section titled “Rest Parameters (ES6)”The rest parameter syntax (...paramName) allows a function to accept an indefinite number of arguments as an array. It must be the last parameter in the function definition.
Example: Rest Parameters
Section titled “Example: Rest Parameters”function sumAll(...numbers) { let total = 0; for (const num of numbers) { total += num; } return total;}console.log(sumAll(1, 2, 3)); // Output: 6console.log(sumAll(10, 20, 30, 40, 50)); // Output: 150console.log(sumAll()); // Output: 0Spread Syntax (...) with Function Calls (ES6)
Section titled “Spread Syntax (...) with Function Calls (ES6)”The spread syntax allows an iterable (like an array) to be expanded into individual arguments in a function call.
Example: Spread Syntax
Section titled “Example: Spread Syntax”function calculateProduct(a, b, c) { return a * b * c;}const values = [2, 3, 4];console.log(calculateProduct(...values)); // Equivalent to calculateProduct(2, 3, 4) -> Output: 24The Function Constructor (Rarely Used)
Section titled “The Function Constructor (Rarely Used)”Functions can also be created dynamically using the Function constructor: new Function(arg1, arg2, ..., functionBody). However, this is generally not recommended due to security risks (similar to eval()) and performance implications, as the function body is parsed at runtime.
Recursion
Section titled “Recursion”A function that calls itself is recursive. Recursion is useful for solving problems that can be broken down into smaller, self-similar subproblems. A base case is needed to stop the recursion.
Example: Factorial using Recursion
Section titled “Example: Factorial using Recursion”function factorial(n) { if (n < 0) return undefined; // Factorial not defined for negative numbers if (n === 0 || n === 1) { return 1; // Base case } else { return n * factorial(n - 1); // Recursive step }}console.log(factorial(5)); // Output: 120Immediately Invoked Function Expressions (IIFE)
Section titled “Immediately Invoked Function Expressions (IIFE)”An IIFE is a function that is defined and executed immediately. Historically, IIFEs were used to create a private scope for variables to avoid polluting the global scope (using var). With ES6 let and const providing block scope, and modules providing true encapsulation, the need for IIFEs for scope management has diminished, but they can still be useful for initialization or to create closures.
Example: IIFE
Section titled “Example: IIFE”(function() { const message = "This is from an IIFE!"; console.log(message);})();// message is not accessible hereGenerator Functions (ES6)
Section titled “Generator Functions (ES6)”Generator functions (function* name() { ... }) are a special type of function that can be paused and resumed, allowing them to produce a sequence of values over time. They use the yield keyword to pause and return a value. When called, a generator function returns an iterator object.
Example: Generator Function
Section titled “Example: Generator Function”function* countUpTo(max) { let count = 1; while (count <= max) { yield count++; // Pause and yield the current count }}
const counter = countUpTo(3);console.log(counter.next()); // { value: 1, done: false }console.log(counter.next()); // { value: 2, done: false }console.log(counter.next()); // { value: 3, done: false }console.log(counter.next()); // { value: undefined, done: true }
// Can also be used with for...of loopfor (const num of countUpTo(3)) { console.log(`For...of: ${num}`);}Generators are foundational for advanced asynchronous patterns like those used in async/await (though async/await itself is a higher-level abstraction over promises).