Skip to content

Instantly share code, notes, and snippets.

@ericelliott
Last active February 10, 2016 20:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericelliott/08f8a1834d83b0c7a8ed to your computer and use it in GitHub Desktop.
Save ericelliott/08f8a1834d83b0c7a8ed to your computer and use it in GitHub Desktop.
What's in a name?
/*
UPDATE: This bug has been fixed, but be warned:
concise methods and unnamed function expression assignments
in object literals DO NOT make the function name
available to reference inside the function body.
If you want method recursion, always use a named
function expression.
*/
/*
Babel supports tail call optimization for functions that
have a function call in tail position.
*/
// This...
let foo = function foo (count, limit) {
c = count + 1;
console.log(c);
if (c >= limit) {
return c;
}
return foo(c, limit);
}
// Gets compiled to:
"use strict";
var foo = function foo(_x, _x2) {
var _again = true;
_function: while (_again) {
_again = false;
var count = _x,
limit = _x2;
c = count + 1;
console.log(c);
if (c >= limit) {
return c;
}
_x = c;
_x2 = limit;
_again = true;
continue _function;
}
};
/*
Note that instead of calling the function and allocating a new
stack frame, babel is able to optimize this into a while loop...
But watch what happens if we omit the name in the function
expression...
*/
let foo = function (count, limit) {
// This first line is all we changed...
// Compiles to
"use strict";
var foo = (function (_foo) {
function foo(_x, _x2) {
return _foo.apply(this, arguments);
}
foo.toString = function () {
return _foo.toString();
};
return foo;
})(function (count, limit) {
c = count + 1;
console.log(c);
if (c >= limit) {
return c;
}
return foo(c, limit);
});
/*
Why is this happening? Because the ES6 spec
specifies that JS engines should infer function
names when they're not provided so they can
provide better stack traces than a big
block of (Anonymous) function calls.
In the example, Babel is jumping through hoops to
make the function name behave as expected in the
debugger... at the expense of the tail call
optimization!
The result is, for the sake of a minor
convenience in the debugger, Babel risks blowing
up the stack frame and breaking your program.
Oops! So, remember to always name
your function expressions, even with ES6
(if you're compiling to ES5).
I filed this as a bug here:
https://github.com/babel/babel/issues/1367
*/
@ericelliott
Copy link
Author

Now there's a custom ESLint rule for this issue. Use it! =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment