Chapter 2: JavaScript Functions and Scope - Complete Guide to Function Programming
Functions are one of the core concepts of JavaScript programming and the building blocks of modular, reusable code. This comprehensive chapter will introduce function definition, invocation, parameter passing, scope, closures, and advanced function concepts that make JavaScript a powerful and flexible language.
Why Functions Matter in JavaScript
Functions in JavaScript are essential because they:
- Enable Code Reusability: Write once, use many times
- Improve Code Organization: Break complex problems into manageable pieces
- Support Functional Programming: First-class functions enable powerful programming patterns
- Handle Scope Management: Control variable visibility and lifetime
- Enable Asynchronous Programming: Callbacks, promises, and async/await
Learning Objectives
Through this chapter, you will master:
- Function definition and invocation
- Parameter passing and return values
- Scope and closures
- Arrow functions
- Higher-order functions
Function Definition
Function Declaration
Function declarations are hoisted and can be called before they are defined:
// This works because function declarations are hoisted
console.log(greet('Alice')); // Hello, Alice!
function greet(name) {
return `Hello, ${name}!`;
}
// Function declarations create a named function
console.log(greet.name); // "greet"
Function Expression
Function expressions are not hoisted and must be defined before use:
// This would cause an error
// console.log(greet('Bob')); // ReferenceError: greet is not defined
const greet = function(name) {
return `Hello, ${name}!`;
};
console.log(greet('Bob')); // Hello, Bob!
// Anonymous function expressions
const anonymous = function() {
return "I'm anonymous";
};
console.log(anonymous.name); // "anonymous" (inferred name)
Arrow Functions (ES6+)
Arrow functions provide a concise syntax and lexical this
binding:
// Basic arrow function
const greet = (name) => `Hello, ${name}!`;
// Single parameter - parentheses optional
const square = x => x * x;
// Multiple parameters
const add = (a, b) => a + b;
// No parameters
const sayHello = () => "Hello!";
// Block body with return statement
const complexFunction = (x) => {
const result = x * 2;
return result + 1;
};
// Arrow functions don't have their own 'this'
const obj = {
name: "John",
regularFunction: function() {
console.log(this.name); // "John"
},
arrowFunction: () => {
console.log(this.name); // undefined (or global this)
}
};
Arrow Functions
const greet = (name) => {
return `Hello, ${name}!`;
};
// Simplified syntax
const greet = name => `Hello, ${name}!`;
console.log(greet('Charlie')); // Hello, Charlie!
Parameter Passing
Basic Parameters
function add(a, b) {
return a + b;
}
console.log(add(5, 3)); // 8
Default Parameters
function greet(name = 'World') {
return `Hello, ${name}!`;
}
console.log(greet()); // Hello, World!
console.log(greet('Alice')); // Hello, Alice!
Rest Parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum(1, 2)); // 3
Scope
Global Scope
const globalVar = 'I am global';
function testScope() {
console.log(globalVar); // I am global
}
testScope();
Local Scope
function testScope() {
const localVar = 'I am local';
console.log(localVar); // I am local
}
testScope();
// console.log(localVar); // ReferenceError: localVar is not defined
Block Scope
if (true) {
const blockVar = 'I am in block';
let blockLet = 'I am also in block';
}
// console.log(blockVar); // ReferenceError
// console.log(blockLet); // ReferenceError
Closures
A closure is when a function can access variables from its outer scope.
function outerFunction(x) {
// Outer function
return function innerFunction(y) {
// Inner function
return x + y;
};
}
const addFive = outerFunction(5);
console.log(addFive(3)); // 8
console.log(addFive(10)); // 15
Practical Application of Closures
function createCounter() {
let count = 0;
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
Higher-Order Functions
Higher-order functions are functions that accept functions as parameters or return functions.
Accepting Functions as Parameters
function processArray(arr, processor) {
return arr.map(processor);
}
const numbers = [1, 2, 3, 4, 5];
const doubled = processArray(numbers, x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
Returning Functions
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Common Array Methods
map
const numbers = [1, 2, 3, 4, 5];
const squared = numbers.map(x => x * x);
console.log(squared); // [1, 4, 9, 16, 25]
filter
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = numbers.filter(x => x % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]
reduce
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15
Practice Project: Calculator
Create a fully functional calculator:
class Calculator {
constructor() {
this.history = [];
}
add(a, b) {
const result = a + b;
this.history.push(`${a} + ${b} = ${result}`);
return result;
}
subtract(a, b) {
const result = a - b;
this.history.push(`${a} - ${b} = ${result}`);
return result;
}
multiply(a, b) {
const result = a * b;
this.history.push(`${a} * ${b} = ${result}`);
return result;
}
divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
const result = a / b;
this.history.push(`${a} / ${b} = ${result}`);
return result;
}
getHistory() {
return this.history;
}
clearHistory() {
this.history = [];
}
}
// Usage example
const calc = new Calculator();
console.log(calc.add(10, 5)); // 15
console.log(calc.multiply(3, 4)); // 12
console.log(calc.getHistory());
// ["10 + 5 = 15", "3 * 4 = 12"]
Summary
This chapter introduced JavaScript functions and scope, including:
- Function definition and invocation methods
- Parameter passing and default parameters
- Scope and closure concepts
- Arrow functions and higher-order functions
- Common array methods
Mastering functions and scope is fundamental to JavaScript programming and provides the foundation for learning more advanced concepts.