javascriptperformanceoptimizationself-documenting-code

Do the most current JavaScript/ECMAScripte compilers optimize out unnecessary variable assignment when returning the value from a function call?


Say we are inside an object that implements file handling. I want to write the code for easier readability.

Example of code where it can be difficult to tell the return type, especially when there are multiple nested function calls:

function create() {
    return doCreateAction();
}

This example is more readable by introducing a clarifying variable:

function create() {
    var fileHandle = doCreateAction();
    return fileHandle;
}

In theory, the second version could perform identically because the compiler has to store the result from doCreateAction() temporarily anyway (probably inside some hiddenm, anonymous, short-lived temp variable). It this code any slower when assigning to a named variable?


Solution

  • I would say either they do optimize the variable out, or it's not worth bothering; and that in either case you have bigger fish to fry. :-) But there is an interesting aspect to this in relation to tail calls.

    But first, in terms of simple performance: Empirically, this simplistic, synthetic test suggests that the performance of the function doesn't vary depending on whether there's a variable. Also note that a minifier will likely remove that variable for you before the JavaScript engine gets a look in, if you use a decent minifier.

    Moving on to tail-calls: As you may know, as of ES2015 in strict mode the specificaton requires tail-call optimization (TCO), which means that when function A returns the result of calling function B, rather than having B return its result to A which then returns it to the caller, A passes control directly to B which then returns the result to the caller. This is more efficient in several ways (avoids creating another frame on the stack, avoids a jump).

    Now, it may not matter because development of TCO in JavaScript engines is at least stalled if not dead. The V8 team developed an early version but abandoned it, SpiderMonkey doesn't have it either; as far as I know, only JavaScriptCore in Safari does TCO. But if I read the spec correctly (no mean feat), your first example has doCreateAction in the tail position and so can be optimized via TCO, but your second does not.

    So there could be implications in that regard, if and when TCO is ever implemented widely and if, when it is, implementations go slightly beyond the spec for cases like this where clearly it is, in effect, a tail call.


    I used to be fairly strict about using a variable in that situation for debugging purposes; moderately-recent versions of Chrome's devtools make it unnecessary for that purpose however (and of course, a minifier will remove it anyway): If you step into a return, you see the return value in the local scope list of variables. Of course, that's only useful if you're using Chrome's devtools (Firefox's, for instance, don't do this [yet?]).