0

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?

djenning90
  • 197
  • 1
  • 9
  • 1
    "It this code any slower when assigning to a named variable?" have you tried to do some benchmarks on your own? Off-topic. I'd say you better rename your functions :) Why `doCreateAction` returns something that is better described as `fileHandle`? Why don't you call it `createFileHandle` or something. – Yury Tarabanko Jul 26 '17 at 09:56
  • 1
    In such a trivially-obvious case? I'd be truly, massively astonished if they didn't. Do I know that to be the case? No, I haven't inspected the optimizer code for all of the main JavaScript engines (much less all their variants; V8, for instance, currently uses both an interpreter and a compiler, where until fairly recently it used two compilers). – T.J. Crowder Jul 26 '17 at 09:59
  • And you want to know this....why? –  Jul 26 '17 at 11:06
  • If you are concerned about performance, you might want to look into [UglifyJS](http://lisperator.net/uglifyjs/), [Closure Compiler](https://developers.google.com/closure/compiler/), [prepack](https://github.com/facebook/prepack), or similar tools. But do not sacrifice the readability of your code. And avoid micro-optimization such as the one in your question. – str Jul 26 '17 at 11:24
  • `const create = doCreateAction; // returns file handle`? :-) – Bergi Jul 26 '17 at 11:41

1 Answers1

2

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?]).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875