Class 10: JavaScript Functions
In the previous class, we explored JavaScript control flow, allowing our programs to make decisions and repeat tasks. Now, we'll delve into Functions, a fundamental building block of JavaScript that enables you to organize code, promote reusability, and make your programs more modular and efficient.
Defining and Calling Functions
A function is a block of code designed to perform a particular task. Functions are executed when "something" invokes (calls) them.
Function Declaration
The most common way to define a function.
// Defining a function named 'greet'
function greet() {
console.log("Hello, welcome to JavaScript functions!");
}
// Calling (invoking) the function
greet();
-
Use the
function
keyword, followed by the function name, parentheses()
, and curly braces{}
containing the code block. - To execute the function, simply call it by its name followed by parentheses.
Function Expression
You can also define a function and assign it to a variable.
// Defining a function expression
const introduce = function() {
console.log("I am a function expression.");
};
// Calling the function expression
introduce();
-
The function is assigned to a
const
orlet
variable. -
It can be an anonymous function (without a name after
function
).
Function Parameters and Return Values
Functions can accept input values (parameters) and produce output values (return values).
Parameters
Parameters are placeholders for values that a function expects to receive when it's called.
function greetPerson(name) { // 'name' is a parameter
console.log(`Hello, ${name}!`);
}
greetPerson("Alice"); // "Alice" is an argument
greetPerson("Bob"); // "Bob" is an argument
- Parameters are listed inside the parentheses in the function definition.
- Arguments are the actual values passed to the function when it's called.
Return Values
The return
statement is used to send a value back
from the function to the caller.
function add(a, b) {
let sum = a + b;
return sum; // The function returns the sum
}
let result1 = add(10, 5);
console.log(result1);
function multiply(x, y) {
return x * y; // Concise return
}
let result2 = multiply(4, 7);
console.log(result2);
function doNothing() {
// If no return statement, the function implicitly returns 'undefined'
}
console.log(doNothing());
-
When JavaScript reaches a
return
statement, the function stops executing. - Functions can return any data type: numbers, strings, booleans, objects, arrays, or even other functions.
-
If no
return
statement is specified, the function implicitly returnsundefined
.
Scope
Scope determines the accessibility (visibility) of variables and other resources in your code. In JavaScript, there are mainly two types of scope: Global Scope and Local Scope.
Global Scope
Variables declared in the global scope can be accessed from anywhere in your code.
let globalVar = "I am global";
function accessGlobal() {
console.log(globalVar); // Accessible from within a function
}
accessGlobal();
console.log(globalVar); // Accessible outside the function
Local Scope
Variables declared inside a function are local to that function and cannot be accessed from outside it.
function demonstrateLocalScope() {
let localVar = "I am local to this function";
console.log(localVar); // Accessible inside the function
}
demonstrateLocalScope();
// console.log(localVar); // This would cause a ReferenceError: localVar is not defined
- Each time a function is called, a new local scope is created.
- This helps prevent naming conflicts and keeps variables isolated.
Hoisting
Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase.
Function Declaration Hoisting
Function declarations are fully hoisted, meaning you can call them before they are defined in your code.
// This works because 'myFunction' declaration is hoisted
myFunction();
function myFunction() {
console.log("Hello from hoisted function!");
}
Variable Hoisting (var
, let
,
const
)
var
declarations are hoisted, but only their
declaration, not their initialization. let
and
const
are also hoisted, but they are in a "Temporal
Dead Zone" until their declaration is encountered, preventing
access before initialization.
// Using 'var'
console.log(x); // Output: undefined (declaration is hoisted, but not initialization)
var x = 10;
console.log(x);
// Using 'let' (causes an error if accessed before declaration)
// console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 20;
console.log(y);
// Using 'const' (causes an error if accessed before declaration)
// console.log(z); // ReferenceError: Cannot access 'z' before initialization
const z = 30;
console.log(z);
Function Expression Hoisting
Function expressions (including arrow functions) are treated like variable declarations when it comes to hoisting.
// This will cause a TypeError or ReferenceError because 'myFuncExpression' is not yet a function
// myFuncExpression();
const myFuncExpression = function() {
console.log("Hello from function expression!");
};
myFuncExpression();
Exception Handling: try...catch
and
finally
In JavaScript, errors or "exceptions" can occur during program execution. Exception handling provides a way to gracefully deal with these errors, preventing your program from crashing and allowing you to provide meaningful feedback or recovery mechanisms.
The try...catch
Statement
The try...catch
statement allows you to test a
block of code for errors and handle them if they occur.
try {
// Code that might throw an error
// This example accesses an undefined variable, which will cause a ReferenceError
console.log(nonExistentVariable);
console.log("This line will not be executed if an error occurs above.");
} catch (error) {
// Code to handle the error
console.error("An error occurred:", error.message);
// You can also log the full error object: console.error(error);
}
console.log("Program continues after try...catch block.");
// Example with a custom error
function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed.");
}
return a / b;
}
try {
console.log(divide(10, 2));
console.log(divide(10, 0)); // This will throw a custom error
} catch (error) {
console.error("Caught a division error:", error.message);
}
-
The
try
block contains the code that you want to monitor for errors. -
If an error occurs within the
try
block, the execution jumps to thecatch
block. -
The
catch
block receives anerror
object as a parameter, which contains information about the error (e.g.,name
,message
). -
If no error occurs in the
try
block, thecatch
block is skipped.
The finally
Block
The finally
block executes regardless of whether an
error occurred or was caught. It's often used for cleanup
operations.
function executeOperation() {
try {
console.log("Inside try block.");
// Simulate an error sometimes
const randomNumber = Math.random();
if (randomNumber > 0.5) {
throw new Error("Something went wrong!");
}
console.log("Operation successful!");
} catch (error) {
console.error("Caught an error:", error.message);
} finally {
console.log("Finally block always executes (cleanup or final message).");
}
}
executeOperation();
executeOperation(); // Call it again to see both success and error scenarios
-
The
finally
block runs aftertry
andcatch
(if present), before the code following thetry...catch...finally
construct. - It's useful for releasing resources, closing files, or performing any other actions that must happen regardless of the outcome.