return vs console.log in JavaScript
return vs console.log in JavaScript is not a choice between two ways to show a value. console.log prints a value for a human. return sends a value back to the code that called the function. A function can log the correct answer and still give its caller undefined, which is why this confusion breaks tests, array methods, UI rendering, and almost every "why is my variable undefined?" debugging session.
The practical rule is blunt: use return when other code needs the value. Use console.log when you want to inspect what is happening.
The short version
| Code | What it does | Who receives the value |
|---|---|---|
return value | Sends value out of the function and stops that function call | The caller |
console.log(value) | Prints value to the console | The person reading the console |
They can appear near the same calculation, but they do different jobs.
function double(number) {
console.log(number * 2);
}
const result = double(4);
console.log(result); // undefined
The first log prints 8. That does not mean double(4) produced 8 as a reusable value. The function never returned anything, so the call result is undefined.
console.log is output for inspection
console.log writes to the console. That is useful while learning and debugging because it turns invisible program state into something visible.
function formatUsername(username) {
const cleaned = username.trim().toLowerCase();
console.log(cleaned);
}
formatUsername(" ADA "); // logs "ada"
This proves the calculation happened. It does not make the cleaned username available to the next line of code.
const savedName = formatUsername(" ADA ");
console.log(savedName); // undefined
The log was a side effect. It affected the outside world by printing text, but it did not become the function's result.
return sends a value to the caller
return is how a function answers the call.
function formatUsername(username) {
const cleaned = username.trim().toLowerCase();
return cleaned;
}
const savedName = formatUsername(" ADA ");
console.log(savedName); // "ada"
Now the caller can store the value, compare it, pass it to another function, render it, or test it.
function makeProfileLabel(username) {
const savedName = formatUsername(username);
return `@${savedName}`;
}
makeProfileLabel(" ADA "); // "@ada"
That is the whole point of return values. They let small functions compose into larger behavior.
The bug: logging instead of returning
This is the beginner bug that looks correct because the console shows the right number:
function addTax(price) {
console.log(price * 1.2);
}
const total = addTax(50);
console.log(total); // undefined
If the task is "show the total once," logging might look fine. If the task is "calculate the total so checkout can use it," the function is broken.
Return the value:
function addTax(price) {
return price * 1.2;
}
const total = addTax(50);
console.log(total); // 60
This matters even more in array methods. map uses the callback's return value to build the new array:
const prices = [10, 20, 30];
const discounted = prices.map((price) => {
console.log(price * 0.8);
});
console.log(discounted); // [undefined, undefined, undefined]
Each callback logged a discounted price, but none returned one. The fixed version returns the transformed value:
const discounted = prices.map((price) => {
return price * 0.8;
});
console.log(discounted); // [8, 16, 24]
For the larger method choice, see forEach vs map in JavaScript.
You can log and return
Sometimes you want both: inspect the value and still give it back to the caller.
function calculateDiscount(price, percent) {
const discount = price * percent;
console.log({ price, percent, discount });
return discount;
}
const discount = calculateDiscount(80, 0.25);
const finalPrice = 80 - discount;
console.log(finalPrice); // 60
That is fine while debugging. The important part is knowing which line is doing which job. The log helps you inspect. The return keeps the program usable.
return stops the function
return also ends the current function call immediately.
function getAccessLabel(isLoggedIn) {
if (!isLoggedIn) {
return "Please sign in";
}
return "Welcome back";
}
Once the first return runs, the function is done. Code later in the function body does not run for that call.
function brokenGreeting(name) {
return `Hello, ${name}`;
console.log("This never runs");
}
This is useful for early exits. It is also why logging after a return will not help you debug anything. The code is unreachable.
Functions without return return undefined
JavaScript functions always produce a call result. When there is no explicit returned value, that result is undefined.
function sayHi(name) {
console.log(`Hi, ${name}`);
}
const message = sayHi("Mira");
console.log(message); // undefined
A bare return behaves the same way:
function stopIfEmpty(items) {
if (items.length === 0) {
return;
}
return items[0];
}
stopIfEmpty([]); // undefined
That can be a deliberate signal, but it should be deliberate. "I forgot to return" and "this case returns undefined on purpose" are very different programs wearing the same coat.
Arrow functions have one extra trap
Arrow functions can return an expression automatically:
const double = (number) => number * 2;
But if you add braces, you need return:
const brokenDouble = (number) => {
number * 2;
};
brokenDouble(4); // undefined
The fixed block-bodied version is explicit:
const double = (number) => {
return number * 2;
};
The JavaScript Arrow Functions guide covers this syntax in more detail.
When to use each
Use return when:
- Another line of code needs the value.
- A test should verify the result.
- A function represents a calculation or transformation.
- A callback must provide a value to
map,filter,reduce, or another higher-order function.
Use console.log when:
- You are checking whether code runs.
- You are inspecting an intermediate value.
- You are comparing what you expected with what the program actually did.
- You are temporarily debugging a branch, loop, callback, or function call.
The clean version of most code returns useful values and logs only when inspection is needed.
Key Takeaways
console.logprints a value for a human; it does not send that value back to the caller.returnsends a value out of the function and stops the current function call.- A function that only logs will return
undefinedunless it also has a return value. - Array callbacks often need returned values, especially with
map. - Good debugging logs answer a question, but good functions still return the values other code needs.