A function that computes something without handing it back is useless: the result exists for a fraction of a second, then vanishes with it. return is the only route by which a value leaves a function.
It is also an exit statement, and that second role is the one people use least, even though it makes code far easier to read.
Definition
return stops the current function immediately and hands the value written to its right back to whatever made the call. Everything below it in the body is abandoned, even inside the same braces.
function discount(amount) {
if (amount < 100) {
return 0; // immediate exit, the rest is never read
}
return amount * 0.1;
}
console.log(discount(50), discount(300)); // 0 30A function may hold as many return statements as needed. The first one reached wins, the others are never evaluated.
With no return, the function gives back undefined
A function whose body ends without meeting a return gives back undefined. So does a bare return written with no value, which exists precisely to leave early without communicating anything.
function log(message) {
console.log(message);
}
console.log(log("hello")); // hello, then undefinedThat distinction explains a very common beginner bug: printing a value with console.log and believing it was returned. Printing serves whoever is watching the screen, return serves the code that made the call. The two have nothing to do with each other.
The automatic semicolon trap
JavaScript inserts semicolons wherever it decides a statement has ended. With return, the rule is strict: nothing may move to the next line between the keyword and the value.
function position() {
return
{ x: 1 };
}
console.log(position()); // undefinedThe engine read return; and then an isolated block it ignored. No error, no warning, only an empty value. This is one of the rare places in the language where a line break changes the meaning of the program, and the reason the value always starts on the same line as the keyword.
Inside an async function, return does not hand back the value directly but a Promise already resolved with it. The caller therefore has to wait for it with await before using it.
Frequently asked questions
Can several values be returned at once?
Not directly, but an object or an array does the job nicely, and Destructuring unpacks them in one line on the caller's side. The object is preferable as soon as there are more than two values, because it names them instead of filing them in an order somebody has to remember.
Why does my return not leave the loop?
Because it does not leave a loop, it leaves a function. Written inside the callback passed to Array.forEach(), it ends that callback for the current item, exactly like a continue, and the walk carries on. To actually interrupt a walk you need a for loop with break, or a method that stops on its own such as Array.find().
Should a function have a single return?
That is an old rule inherited from other languages, and it no longer holds. Leaving early on the special cases, at the top of the function, avoids nesting three levels of conditions only to reach one useful line. The case worth pausing on is a long function whose exits are scattered: the problem is no longer return, it is the function, which would gain from being split up.