Is there a benefit to using a return statement that returns nothing?

Viewed 85266

I'm refactoring a large javascript document that I picked up from an open source project. A number of functions use inconsistent return statements. Here's a simple example of what I mean:

var func = function(param) {
    if (!param) {
        return;
    }
    // do stuff
    return true;
}

Sometimes the functions return boolean, sometimes strings or other things. Usually they are inconsistently paired with a simple return; statement inside of a conditional.

The problem is that the code is complex. It is a parser that uses a multitude of unique RegEx matches, creates and destroys DOM nodes on the fly, etc. Preliminary testing shows that, in the above example, I could change the return; statement to become return false;, but I'm concerned that I may not realize that it had a negative impact (i.e. some feature stopped working) on the script until much later.

So my questions: Is there a benefit to using a blank return statement? Could this have been intentionally coded this way or was it just lazy? Can I change them all to return false;, or return null; or do I need to dig through every call and find out what they are doing with the results of those functions?

5 Answers

There is no difference at all between return; and return undefined;. The result of calling both functions is to receive the value undefined.

(There's a very small specification-level difference between a function body that terminates with return vs. just falling off the end of the code, but it's nothing that can be detected in code.¹ Calling a function where execution falls off the end of the code also results in the value undefined.)

"use strict";

// Implicit return of `undefined`
function x() {
    return;
}
// Explicit return of `undefined`
function y() {
    return undefined;
}
// Execution falls off the end
function z() {
}
console.log(typeof x() === "undefined"); // true
console.log(typeof y() === "undefined"); // true
console.log(typeof z() === "undefined"); // true


Unless, of course, something has shadowed undefined. Which is still sadly possible (though not, gladly, at global scope). In that very edgy edge case, there's a difference:

"use strict";
(function() {
    const undefined = 42;
//  ^^^^^^^^^^^^^^^---- shadowing `undefined`
    // Implicit return of `undefined`
    function x() {
        return;
    }
    // Explicit return of `undefined`
    function y() {
        return undefined;
    }
    // Execution falls off the end
    function z() {
    }
    console.log(typeof x() === "undefined"); // true, `x` returns the canonical `undefined`
    console.log(typeof y() === "undefined"); // false, `y` returns 42
    console.log(typeof z() === "undefined"); // true, `z` (effectively) returns the canonical `undefined`
})();


¹ Using return is an abrupt completion that [[Call]] converts to a normal completion w/value. Falling off the end of the code is a normal completion (spec) (that [[Call]] ensures supplies undefined for the value). But again, this is a specification level difference, not something that's observable in code.

Related