Deep JavaScript Foundations, v3

Naming Function Expressions

Kyle Simpson

Kyle Simpson

You Don't Know JS
Deep JavaScript Foundations, v3

Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "Naming Function Expressions" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle gives three reasons why named function expressions are superior to anonymous function expressions.

Preview
Close

Transcript from the "Naming Function Expressions" Lesson

[00:00:00]
>> Kyle Simpson: And you're wondering why and thanks for asking, I have three reasons why you should always prefer this thing that's gonna take you more time and effort to write out all those names to those functions, right? We know that one of the classic hard problems in computer science is naming things, and, you're telling me I gotta go come up with all these names.

[00:00:18]
Trust me, I'm in the same boat, every time I write a function, I'm like, I don't know what to call this thing, can't come up with a good name, I understand that. But there are three reasons which I think, together, make a solid case, that that effort is critical, that it's necessary, that you should always, always use name-function expressions.

[00:00:38]
So number one prefer a name function expression, because the name produces or creates a reliable self-reference to the function from inside of itself. That is useful if you're going to make the function recursive. It's useful if that function is an event handler of some sort and it needs to reference itself to unbind itself.

[00:00:58]
It's useful if you need to access any properties on that function object such as its link or its name or other thing of that sort. Anytime you might need a self reference to the function, the single only right answer to that question is, it needs to have a name.

[00:01:14]
There were some pre ES6 sorts of hacks or an even pre ES5 sorts of hacks, where you could use arguments start calling as a reference to the function, it's not broken but essentially deprecated. The way to get a reference to a function from inside of itself and have a reliable reference is to use the name of your function expression.

[00:01:35]
In that previous example, when I had a variable name that was in the global scope, and then I had my function expression. Would it be more or less reliable for me to make a reference to a marble in my own scope that is read only, or to reference a marble in an enclosing scope that is not read only?

[00:01:56]
>> Kyle Simpson: If I wanted to reference myself from inside of the function, and I had the choice between referencing myself with a marble in my own scope that is read only, the name of my function expression. Or I could self-reference myself with the variable that my function had be assigned to in the outer scope, which isn't by default read only.

[00:02:18]
Which one of those two would be the better self reference?
>> Speaker 2: The first one.
>> Kyle Simpson: First one, right, the one that you own and that is read only is a more reliable self reference. So, number one, if there's any possible chance remotely that you're gonna need a self reference, it's best to go ahead and name it.

[00:02:35]
Even if you don't need it now, you might need it in the future, it's best to go ahead and name it, that's reason number one. Reason number two, why you should always prefer named function expressions. How many of you have ever had a JavaScript exception where you had to debug it by looking at a stack trace?

[00:02:53]
Okay, how many of you love seeing anonymous function, over and over again, line after line in your stack traces? Especially, when we're talking about production code that's been minified, so they all say line 1, character 32,712, cuz we all know exactly which function that is, right? Guess what happens if you use a name for your function expressions?

[00:03:15]
It shows up in the stack trace. If you use a good name not like food bar, but like handle user click, it's going to show up in the stack trace. So automatically by naming your functions, you make your code more debuggable, you make your stack traces more debuggable.

[00:03:32]
Truth, I have on multiple occasions, looked at a stack trace that had good, useful semantic names in it, and been able to tell the source of the bug simply by looking at the names and the order of the functions, what didn't get called and what did get called.

[00:03:48]
Didn't even have to look at the code, I knew immediately what the bug was just from having the names. And even if you do have to look at the code, you're still approaching the code with more mental context from that stack trace than you would before. Now I think that rule in and of itself is enough to justify always name your functions.

[00:04:04]
I don't know about you, but I need all the help I can debugging my programs. So, the extra effort is gonna pay off in dividends every time I have to debug the code. Number two, we want to have debuggable stack traces. And number three, and I think personally this might be the most important of all, but it's certainly the one that seems least obvious or maybe it's a little more controversial to other people.

[00:04:28]
Number three, by putting a name on your function, you make that code more self-documenting. If I have a function that is anonymous, and I look at that function to figure out what that anonymous function is doing, I have to read the function body and I also probably have to read where it's being parsed.

[00:04:47]
>> Kyle Simpson: And I have to infer from those two pieces of information, the purpose of the function. I may be able to infer the purposes that it handles user clicks. But I would rather the reader not have to infer that its purpose is to handle user clicks when I could put a name there that makes it completely and totally unambiguous.

[00:05:08]
The function named handle user clicks doesn't require any other reading of the rest of the code, for me to figure out, you want me to handle user clicks with this function, yes?
>> Speaker 3: So this is more of a best practices question seems very compelling. My first instinct is then to say, okay, I'll just name the expression the same thing that I will name the variable of the scope above, I'm assuming, a, is that a case of shadowing?

[00:05:33]
And b,-
>> Kyle Simpson: It is a case of shadowing.
>> Speaker 3: And at B, that's probably incredibly problematic for debris or is that something that would be considered-
>> Kyle Simpson: I wouldn't consider shadowing to be a problem or not a problem. In that particular scenario, I think it is unlikely that you're gonna need to have both references to the function.

[00:05:52]
Maybe you're gonna need to and if you do, you're gonna have to name them something different, you're now gonna have to avoid shadowing. But in most cases, if there is one definitive name for what this thing is, name both of them now if you want to. My personal opinion is don't do function expression on the variable anyway, do a function declaration and there's just one name but, if you are going to make a variable then it probably makes more sense if there's only one name.

[00:06:19]
There are caveats to this, though, because sometimes, the usage of that function, where it's being passed to, or what it's going to do, it may have a different purpose than how you wanna describe it, in and of itself. So it might in fact be that there's a different, more appropriate name for the function, as opposed to what property it's being assigned to, or what variable it's being assigned to.

[00:06:39]
So they are not necessarily the same, but sometimes they might be, helpful? Good, so these three I think, taken together, make an ironclad case that your functions would make better code if your functions are named. Now I understand that that is problematic for most people that have that finger muscle memory of writing the functions anonymously.

[00:07:12]
That I've seen every single blog since the jQuery days, using anonymous functions. That every piece of code you've ever had any access to anonymous functions everywhere. And all of a sudden, here's this one guy telling you, no, no, no, those all need names. I get it, that's problematic, it's troublesome, it's extra work.

[00:07:29]
But you have to go back to what I said about the purpose of code. The purpose of code is not to be convenient for you to type. The purpose of code is for you to communicate more clearly your intent. There are ways to solve each of these problems but the best way to solve these problems is to name the function.

[00:07:49]
So someone asked just a moment ago, what happens if I assign an anonymous function to property, or to a variable or something, what happens to the name? Well, it's still an anonymous function, it still doesn't have a lexical self-reference to itself. Could you reference the variable in the outer scope?

[00:08:05]
Of course you can, but it's a little less reliable, a little less trustable, and I would argue a little less semantic. Is it gonna show up with a name in the stack trace? Depending upon where that function expression exists, it might be able to have a name inferred.

[00:08:19]
For example, if it's assigned to a variable, then generally as long as there isn't some complex destructuring code in place, generally it's going to just take the name and infer that's what you mean for the purposes of the stack trace, except here is the big problem, 99.9% of all cases where people use anonymous functions expressions is as callbacks.

[00:08:42]
They pass them in line directly to other functions like .map, .then, all those and guess what? When you pass a function expression in a call position, there's no way to infer any name from it. So you don't get the benefit of that name inference, you have to assign it to a variable to get the name inference or to a property.

[00:09:01]
And if you're gonna go to the trouble to assign it to a variable why not just make it a declaration? Why write a variable and then have to write the name twice? I don't see any reason why you should strongly prefer making more work for yourself and making it a little bit more confusing for people.

[00:09:15]
And that's not even the only difference, when we talk about hoisting later we're gonna see there's a big difference in hoisting. So I think you should prefer function declarations with names if you're gonna pass in a function expression, put a name on it just like you would have if it were a function declaration, give it the same name.

[00:09:31]
Now I understand that naming is hard but really the only legitimate reason why you don't name your functions cuz you're too lazy or uncreative to come up with a name. There is no reason why an anonymous function is preferrable. There is no argument that can be made that that name is distracting or is unhelpful for the purposes of code readability.

[00:09:52]
Any argument that people have made to that extent is complete bunk. People tell you all over the place in books and blogs, no, no, no, all that extra stuff is totally unnecessary. And they're thinking completely wrongly about this, cuz they're not thinking about the purpose of good semantic names.

[00:10:08]
The purpose of a function name is to tell you why does this thing exist. My assertion is that every function that exists in your program, every single function has a purpose. And if every function has a purpose, it means every function has a name. And it's up to you to come up with that name and put it in your code, not make the reader of your code have to figure it out every single time they read the code.

[00:10:33]
If you can not come up with a name for the function, it probably means that you don't understand that function yet. It probably means, that function is too complex, and needs to be broken down into smaller pieces until such a time as those names are completely self obvious, and then put them there.

[00:10:53]
It's a leading indicator of more problematic code when you can't come up with a name or the name that you can come up with is 14 words long like we do in Java, okay? That usually means this function is doing too much. There was a question over here, yes?

[00:11:08]
>> Speaker 4: So are you saying that the use of anonymous functions is really just to type less, that's really all.
>> Kyle Simpson: That's exactly what I'm saying, and it gets worse when we go to the next slide, yes.
>> Speaker 5: So it sounds like you definitely prefer declarations, is there ever, is there a good use for a function expression?

[00:11:31]
>> Kyle Simpson: Yeah, absolutely, function expression sometimes are absolutely necessary. My personal rule of thumb, other than places where you have to, my personal rule of thumb is that I prefer function declaration if it's more than three lines of code. If it's one, two, or three lines of code, generally I'm gonna make that an inline function expression.

[00:11:50]
Unless, that thing needs to be called multiple times, in which case, I'm gonna make it a function declaration, even if it's one line.
>> Kyle Simpson: But those are just sort of general guidelines in case, your mileage may vary, as they say, okay? So guess what, I still struggle with this, even though for years I've been preaching this message and telling people.

[00:12:12]
And you're the 10,000th student to ever hear me say this, right? I've said this all over the world for years and I still struggle with this problem and here's the trick that I use. Number one, I don't ever write code just once and then I'm done with it, code is always an iterative process where I'm refactoring it.

[00:12:29]
When I start to write a function, I almost certainly don't know yet exactly how and what that function's gonna be for or what the structure's gonna be. So I just accept the fact that whatever name I come up with is not written in stone and I'm gonna change it multiple times.

[00:12:43]
And if I legitimately can't come up with any good name yet, I start with the name TODO, T-O-D-O because I'm in a habit of searching for TODO comments before I commit things. And I'll find those unnamed functions and at that point maybe have a better sense of what it ought to be called.

[00:13:03]
Still a process that you have to work on, it is still an effort, and it still my extinctual habit even all these years later that I start with the anonymous function but then I realized all of these benefits and I go back and I name them.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now