56

I'm taking a course in JavaScript programming, and the instructor said that a typical JavaScript function always returns a value. Even when we don't provide any explicit return value, the engines return undefined.

Is that true? If so, why?

Teun Zengerink
  • 4,277
  • 5
  • 30
  • 32
Luís Assunção
  • 771
  • 1
  • 8
  • 20
  • 1
    What should contains fuction return value if there is no function return value (for example if you assign it to some variable)? :))) I think it should be 'undefined'. What else could be instead? :) – Dmitry Sikorsky Jan 04 '14 at 00:59
  • it's easier to write a js engine if every function returns something, same for missing properties that show up as undefined. now if only it returned the tail value instead of undefined... – dandavis Jan 04 '14 at 04:18

4 Answers4

94

It's true—because that's how JavaScript was designed.

But I don't think that's the answer you were looking for, so let's think about it...
Try to put yourself in the shoes of Brendan Eich, the person who designed JavaScript!

In static languages, there is usually a distinction between a function that doesn't return anything (void function), and a function that returns some value. Brendan chose to design a dynamic language, that is, a language that doesn't require you to define function return types. So JavaScript doesn't check what you return from the function, giving you full freedom.

You can have a function that returns a number...

function computeSomething() {
  return 2;
}

... or a string ...

function computeSomething() {
  return 'hi';
}

... or, in fact, any of them:

function computeSomething() {
  if (Math.random() > 0.5) {
    return 2;
  } else {
    return 'hello';
  }
}

Sometimes you don't need to compute anything—you only need to do something.
So you don't return anything.

function doSomething() {
   console.log('doing something');
}

We may, however, want to exit a function in the middle of it, and since return <value> already does exactly that, it makes sense to allow writing return without a value to support this use case:

function doSomething(num) {
   if (num === 42) {
     return;
   }

   while (true) {
     doSomethingElse();
   }
}

This is also consistent with C/Java syntax, which was one of the goals to ensure JavaScript adoption.

Aye, there's the rub: what happens if we put a plain return into a function supposed to compute something? Note that we can't outlaw this: one of our earlier decisions was to make JavaScript a dynamic language, where we don't check what the function returns.

function computeSomething(num) {
  if (num === 42) {
    return; // just return? o_O
  }

  if (Math.random() > 0.5) {
    return 2;
  } else {
    return 'hello';
  }
}

var x = computeSomething(2); // might be 2, might be 'hello'
var y = computeSomething(42); // ???

Of course Brendan could have decided to raise an error in this case, but he wisely decided not to, because it would lead to hard-to-find errors and too easily breakable code.

So an empty return got a meaning “return undefined”.

But what's the difference between the function returning early, or at its end? There shouldn't be any, from the calling code's point of view. Calling code is not supposed to know when exactly the function returned; it is only interested in return value (if any).

The only logical conclusion thus would be to make undefined the “default” return value if function does not specify one via explicit return <value> operator. Thus, return and function-executed-to-its-end semantics match.

Python, another dynamic language that came before JavaScript, solves this problem in the same way: None is returned if function doesn't specify return value.

Alireza
  • 100,211
  • 27
  • 269
  • 172
Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
  • 9
    People always whine about the bad parts of JavaScript—and there are plenty—but boy, there are just **so many** parts of the language that are simply beautiful. – Adam Rackis Jan 04 '14 at 01:55
  • 10
    Great answer! Instead of just regurgitating part of the spec, you analyze the implications and reasons for this design decision. – Peter Jan 04 '14 at 02:36
  • 2
    The idea of a "default/undefined" value is useful in general as a concept in languages. Once you introduce one you can do simple things like checking if an argument was passed (as is done in JS), and it would be strange to not return undefined from void functions. – Chris Moschini Jan 07 '14 at 23:12
13

That's by ECMAScript specification

13.2.1 [[Call]] ... 6. Otherwise result.type must be normal. Return undefined.

Essentially any JS function is compiled as if it has implicit return undefined; at the end:

function foo() {
  ...

  return undefined; // implicit non-visible statement  
}
c-smile
  • 26,734
  • 7
  • 59
  • 86
  • Latest link as of 2022: https://262.ecma-international.org/12.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist – wlnirvana Mar 30 '22 at 06:24
7

Even when we don't provide any explicit return value, the engines return "undefined". Is that true?

Not really. As I understand it, a function that returns nothing...returns nothing. That said, if you assign a variable to the result of such a function invocation, then the expression will evaluate to undefined.

EDIT

I stand corrected. Here's the relevant portion of the spec:


13.2.1 [[Call]]

When the [[Call]] internal method for a Function object F is called with a this value and a list of arguments, the following steps are taken:

  1. Let funcCtx be the result of establishing a new execution context for function code using the value of F's [[FormalParameters]] internal property, the passed arguments List args, and the this value as described in 10.4.3.
  2. Let result be the result of evaluating the FunctionBody that is the value of F's [[Code]] internal property. If F does not have a [[Code]] internal property or if its value is an empty FunctionBody, then result is (normal, undefined, empty).
  3. Exit the execution context funcCtx, restoring the previous execution context.
  4. If result.type is throw then throw result.value.
  5. If result.type is return then return result.value.
  6. Otherwise result.type must be normal. Return undefined.
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • 2
    Thanks @Dan - I'm afraid a few upvotes and a bronze badge are about all the remuneration I can offer :) – Adam Rackis Jan 04 '14 at 01:14
  • 1
    "function that returns nothing...returns nothing" is not true. There is no 'nothing' value in JS. It "returns precisely 'undefined'" for the return statement without value. See: 12.9 The return Statement in ECMA specification. – c-smile Jan 04 '14 at 01:23
  • 1
    Bump up for the courage to correct your mistake for all to see. – Neil Feb 10 '15 at 15:14
2

In javascript, functions are objects. Therefore, you can always assign a function to a variable like you would assign any other object and the interpreter will force determine a value (which may be undefined.)

dee-see
  • 23,668
  • 5
  • 58
  • 91
canadaCoder
  • 791
  • 7
  • 4