A hidden dependency
A calculation changes its answer because another part of the program changed a global discount. The function's name and argument stayed the same. What information was missing from its visible contract?
Scope determines where a name is accessible. Top-level names in a script occupy its outer scope. A function introduces a local scope; braces introduce block scope for const and let. Local values help you reason about one operation without inspecting the whole program.
function applyDiscount(subtotal, discountRate) {
const discount = subtotal * discountRate;
return subtotal - discount;
}
console.assert(applyDiscount(100, 0.10) === 90);
console.assert(applyDiscount(100, 0) === 100);
The discount amount is local. Callers supply the policy rate explicitly. Accessing discount outside this function would raise a ReferenceError because the name is not available there.
Guided block trace
const label = "Order";
if (true) {
const label = "Draft";
console.assert(label === "Draft");
}
console.assert(label === "Order");
The inner binding shadows the outer name. This is legal, but unnecessary shadowing can confuse a reader. Use different descriptive names when both concepts matter. Do not confuse a local name with a private, secure storage mechanism: scope organizes access in code.
Independent exercise
Rewrite a quote operation so subtotal and rate arrive as parameters and the discounted amount is returned. Explain why changing a separate display label cannot affect its numeric result.
Correction
The first function already demonstrates this boundary. It reads only its parameters and performs arithmetic. A global label is not one of its inputs. If you read global settings inside it, you reintroduce the hidden dependency.
Review
For every name in a function, identify where its value comes from. Prefer explicit inputs for information that determines the answer; use local intermediate values to make each decision understandable.