Chapter 4 - Functions (JavaScript)
Here's a JavaScript-flavoured version of the same concepts, with small JS examples for each idea.
Defining and calling functions
A function is a mini-program defined with function (or as an arrow function) and run later by calling its name with ().
Example:
function hello() {
console.log("Good morning!");
console.log("Good afternoon!");
console.log("Good evening!");
}
hello();
hello();
Arguments and parameters
Parameters are variables in the function definition; arguments are the actual values you pass in when calling.
Example:
function sayHelloTo(name) { // name is a parameter
console.log("Good morning,", name);
}
sayHelloTo("Alice"); // "Alice" is an argument
sayHelloTo("Bob");
After the function returns, name no longer exists outside the function.
Return values and return
A function call evaluates to its return value, which you specify with return. If no return is used, the function returns undefined.
Example:
function square(x) {
return x * x;
}
const result = square(5); // 25
console.log(result);
console.log(square(3) + square(4)); // 25
Magic 8-ball style function
You can use return plus Math.random() to produce different answers depending on a number.
Example:
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getAnswer(n) {
if (n === 1) {
return "It is certain";
} else if (n === 2) {
return "Ask again later";
} else {
return "Very doubtful";
}
}
console.log(getAnswer(randInt(1, 3)));
undefined and null (equivalent of None)
undefined represents "no value returned." Functions with no explicit return return undefined. JavaScript also has null for explicitly "no value."
Example:
const spam = console.log("Hello!"); // prints Hello!
console.log(spam === undefined); // true
Also, return by itself returns undefined:
function doNothing() {
return;
}
console.log(doNothing() === undefined); // true
Named (keyword) parameters in built-ins
JavaScript doesn't have keyword arguments like Python, but you can achieve similar effects. For console.log, you control output differently:
No-newline output (end=""):
// Node.js
process.stdout.write("Hello");
process.stdout.write("World\n"); // HelloWorld
Custom separator (sep=","):
console.log(["cats", "dogs", "mice"].join(","));
// cats,dogs,mice
The call stack
JavaScript tracks where to return after each function call using a call stack. Each call adds a frame; returning pops that frame and resumes after the call.
Example:
function c() {
console.log("c() starts");
console.log("c() returns");
}
function b() {
console.log("b() starts");
c();
console.log("b() returns");
}
function a() {
console.log("a() starts");
b();
console.log("a() returns");
}
a();
You'll see the order: a() -> b() -> c() -> back out again.
Local vs global scope
Variables created inside functions with let/const live in a local scope; variables created at the top level live in the global scope. Local variables are not visible outside their function.
Example (global can't see local):
function spam() {
const eggs = "local eggs";
}
spam();
// console.log(eggs); // ReferenceError: eggs is not defined
Separate local scopes
Each function call has its own local scope, and different functions' locals cannot see one another's variables.
Example:
function spam() {
const eggs = "spam local";
bacon();
console.log("spam sees:", eggs);
}
function bacon() {
const eggs = "bacon local";
console.log("bacon sees:", eggs);
}
spam();
Here each eggs is separate.
Local scope can read globals
Code inside a function can read global variables (as long as you don't declare a local with the same name).
Example:
const eggs = "global eggs";
function spam() {
console.log(eggs); // reads global
}
spam(); // prints "global eggs"
console.log(eggs);
Same name local and global
You can have a global and a local variable with the same name, but it is confusing and usually best avoided.
Example:
const eggs = "global";
function spam() {
const eggs = "spam local";
console.log(eggs);
}
function bacon() {
const eggs = "bacon local";
console.log(eggs);
}
spam(); // spam local
bacon(); // bacon local
console.log(eggs); // global
Modifying outer variables
JavaScript doesn't have a global keyword. If a variable is declared with let in the outer scope, the function can access and modify it directly (no special keyword needed).
Example:
let eggs = "global";
function spam() {
eggs = "spam"; // modifies the outer variable
}
spam();
console.log(eggs); // spam
With const, you cannot reassign, so use let for mutable globals.
How to tell if a name is local or global
Rules in JavaScript:
- A variable declared at the top level with
let/constis global. - A variable declared inside a function with
let/constis local. - If you assign to a name without declaring it, JavaScript looks up the scope chain (and may accidentally create a global — always use
let/const).
Example:
let eggs = "global";
function spam() {
eggs = "spam"; // modifies global (no let/const)
}
function bacon() {
const eggs = "bacon"; // local (declared with const)
console.log(eggs);
}
function ham() {
console.log(eggs); // reads global
}
spam();
console.log(eggs); // spam
Functions as "black boxes"
You can treat functions as black boxes: know their parameters and return values, but ignore the internal implementation.
Example:
function addTax(amount) {
return amount * 1.1;
}
const total = addTax(100); // you don't care how it computes, just that it returns 110
Exceptions and try/catch
Errors raise exceptions that normally crash the program. try/catch lets you catch and handle them so the program can continue.
Naive version (crashes):
function spam(divideBy) {
if (divideBy === 0) throw new Error("Cannot divide by zero!");
return 42 / divideBy;
}
console.log(spam(2));
console.log(spam(0)); // Error thrown
Handled version:
function spam(divideBy) {
try {
if (divideBy === 0) throw new Error("Cannot divide by zero!");
return 42 / divideBy;
} catch (err) {
console.log("Error: Invalid argument.");
}
}
console.log(spam(2)); // 21
console.log(spam(0)); // prints error, returns undefined
try around calls
You can also put the function calls inside the try block; then any exception raised in them will be caught.
Example:
function spam(divideBy) {
if (divideBy === 0) throw new Error("Cannot divide by zero!");
return 42 / divideBy;
}
try {
console.log(spam(2));
console.log(spam(0));
console.log(spam(1)); // never reached after exception
} catch (err) {
console.log("Error: Invalid argument.");
}
Short program: Zigzag animation
The zigzag program uses an infinite loop, setTimeout/setInterval, and string repetition to animate stars moving back and forth. Press Ctrl+C to stop.
let indent = 0;
let indentIncreasing = true;
const interval = setInterval(() => {
console.log(" ".repeat(indent) + "********");
if (indentIncreasing) {
indent++;
if (indent === 20) indentIncreasing = false;
} else {
indent--;
if (indent === 0) indentIncreasing = true;
}
}, 100);
// Stop with: clearInterval(interval)
Short program: Spike animation
The spike program draws a spike shape that grows and shrinks repeatedly using string replication.
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function spike() {
while (true) {
for (let i = 1; i < 9; i++) {
console.log("-".repeat(i * i));
await sleep(100);
}
for (let i = 7; i > 1; i--) {
console.log("-".repeat(i * i));
await sleep(100);
}
}
}
spike();
Overall idea of the chapter
The chapter shows how to define reusable functions, understand call stacks and variable scopes, avoid overusing globals, and use try/catch to handle errors. JavaScript offers function declarations, arrow functions, block scoping with let/const, and closures that work differently from Python's global keyword, but the core ideas are the same.