Why does the Airbnb style guide say that relying on function name inference is discouraged?

xiaofan2406 picture xiaofan2406 · May 18, 2016 · Viewed 7.5k times · Source
// bad
class Listing extends React.Component {
  render() {
    return <div>{this.props.hello}</div>;
  }
}

// bad (relying on function name inference is discouraged)
const Listing = ({ hello }) => (
  <div>{hello}</div>
);

// good
function Listing({ hello }) {
  return <div>{hello}</div>;
}

This is taken from the Airbnb react style guide. Can someone please explain why "relying on function name inference is discouraged"? Is it just a style concern?

Answer

Brad Colthurst picture Brad Colthurst · May 18, 2016

I think this could also have something to do with the unexpected behaviour that you might run into from implicitly giving a lexical name to what you may expect to be an anonymous function.

Say for example someone understood the arrow function:

(x) => x+2;

To have the regular function equivalent:

function(x) {
  return x+2;
}

It would be pretty easy to expect this code:

let foo = (x) => x+2;

To then be the equivalent of:

let foo = function(x) {
  return x+2;
}

Where the function remains anonymous and would be incapable of referencing itself to do things like recursion.

So if then, in our blissful ignorance, we had something like this happening:

let foo = (x) => (x<2) ? foo(2) : "foo(1)? I should be a reference error";
console.log(foo(1));

It would successfully run because that function obviously wasn't anonymous:

let foo = function foo(x) {
  return (x<2) ? foo(2) : "foo(1)? I should be a reference error";
}  

This could potentially be exacerbated by the fact that in other situations where Babel implicitly adds a name to anonymous functions, (which I think is actually a bit of a side-effect of supporting implicit function names in the first place, though I could be wrong on that), they correctly handle any edge cases and throw reference errors where you would expect.

For example:

let foo = {
  bar: function() {}
} 

// Will surprisingly transpile to..

var foo = {
  bar: function bar() {}
}; 


// But doing something like:

var foo = {
  bar: function(x) {
    return (x<2) ? bar(2) : 'Whats happening!?';
  }
}

console.log(foo.bar(1));

// Will correctly cause a ReferenceError: bar is not defined

You can check 'view compiled' on this quick DEMO to see how Babel is actually transpiling that to maintain the behaviour of an anonymous function.


In short, being explicit with what you are doing is typically a good idea because you know exactly what to expect from your code. Discouraging the use of implicit function naming is likely a stylistic choice in support of this while also remaining concise and straightforward.

And probably hoisting. But hey, fun side trip.