5.1 Function Definitions - Video Tutorials & Practice Problems
Video duration:
12m
Play a video:
Video transcript
<v Instructor>We saw in the first chapter</v> that function calls in JavaScript consist of a name and zero or more arguments enclosed in parentheses. So let's take a look at that in the node console. Our first function was console.log. So we see here the name of the function, which is log. In this case, it's attached to a JavaScript object, console, thus making it also a method. So methods are functions. And here is the argument, in this case, a string, "hello, world!" So a function is just something that takes in zero or more arguments and then does something. Typically it returns a value. In the case of console.log, what it does is it prints out the argument as a side effect and then returns nothing, returns undefined. So let's learn how to define functions of our own. There are actually a couple of common ways to do it. I'll cover the easier to understand and probably still a more common way, and then we'll talk about the other way in a moment. So the most common way at this point, and certainly my preferred way, because it's fairly straightforward, is to use the word function. You say function and then the name of the function. So I'll call it stringMessage. We'll use camel case as usual. And then it takes an argument, which we can name like this, called string. And then we use curly braces, as usual, to indicate a code block. Now, recall that empty strings are false in a boolean context. So I can make a little if else statement based on whether or not this string is empty, like this. String... I'm gonna return a value using the return keyword. Else I'll return a different string. Notice we're not printing these out. This is a return value from the function. So unless we call console.log, it won't actually print out to the screen. It'll appear as a return value in the REPL, but it won't be printed out. And a closing curly brace for the if statement and another one for the function. And there we go. We're gonna have a working string message function. You can see that it returns undefined as a value, similar to what happens when you call console.log. But we can test this by calling stringMessage, like this. Call it on one of our favorite strings, honey badger. So that's not empty. We should get this here, "The string is nonempty," as a return value. And if we give it the empty string, it's an empty string. So this is a very simple function, but it demonstrates the essential components of function definition. It's important to understand that this argument can be named anything we want, pretty much. Any valid JavaScript variable name. By the way, that's the kind of detail, just thinking about what's the valid JavaScript variable name, that you can look up. I don't actually know the answer offhand. If you choose sensible variable names the chances are that they're going be valid, but this is the kind of thing that even experienced programmers will look up on the fly. Just go to Google and type JavaScript valid variable names. There are probably some invalid ones. There definitely are some. You couldn't call it return, for example, or function. These keywords are reserved. But certainly we could call it something like asdf, just the first four letters on the home row of a QWERTY keyboard. So I just wanna demonstrate the principle. You can call this anything. Doesn't have to be called string. It's nice to call it something meaningful for the programmers, but the machine doesn't care. Oops, no, I did that wrong. I need to do if asdf. So that does matter. These have to match up, the names here. But other than that, it doesn't matter. Else other return value. So I've just redefined string message and it should work the same. We can even triple check it like this. Can actually make sure that it's doing something different. We can see here from the return value that in fact we've successfully redefined this function. Being able to define functions lets us fix one of the problems that we've seen so far in this tutorial, namely that sorting even numerical arrays sorts them in so-called alphabetical order or as if they were in a dictionary. So for example, if we have an array like this with numbers in it. Right, these are already in numerical order, but if we sort it by calling the sort method, it gets sorted where the number one is before the number four, which is before the number eight, which is before the number nine. So this is not the sort order that we want. We actually wanna be able to sort this and restore it to this order here, and the way to do that is to pass a function to the sort method. The way it works is that if that function is a comparison method that returns one or in fact any positive value, if the first element is greater than the second element in the comparison as it goes through the array, returns negative one or in fact any negative value if the second value is less than the first value, and otherwise returns zero if they're equal. So that's a little bit abstract. Let's actually write it. Let's write a function called numberCompare. It's gonna compare two numbers, a and b. If a is greater than b, it will return one. This isn't obvious. This is just the kind of thing that you look up the sort function in the documentation and it says, oh, this is how you define a comparison that will give you the right order. This is the way it works. So else. Oops, I wanna say else if a less than b, return negative one, else they're equal. That's the only remaining possibility. Return zero. So we can test it like this. NumberCompare, say, eight and 17. That's negative one because eight is less than 17. So we get to this branch here. We can do, say, 17 and 99. Same thing. But if we go the other way, now that's a positive one. And if they're equal, of course, we'll get the third branch. All right, what good does this do us? Well, do a.sort and give it numberCompare. It'll sort according to the return value of this function. Aha, that's what we wanted. Now it's sorted in ascending order, eight, 17, 42, 99. Now, this seems like an awful lot of trouble just to sort an array numerically, and indeed it is. In a couple sections. I'll show you the answer to one of the exercises that shows how to do this in a much more convenient way using a so-called anonymous function. Before doing that, though, I wanna show you an alternate way to define a function. This was added to JavaScript in ES6 or ECMAScript 6, a big update that I've mentioned before in this tutorial. I don't think it's as clear, but it's more convenient in some contexts, and in any case, it's common enough that it's important to know about it. This is kind of like how you have to know both var and let or const, you have to know both function and this new notation, which is called the fat arrow notation. We'll call this new function altStringMessage. It's an alternate string message. And instead of using the function keyword, we're going to use the let keyword to create a variable binding. So altStringMessage, and then we say equals, and then we give it the parameter, in this case string, and then we use the fat arrow, which is equals greater than sign, and then we give it a definition. In this case, I'll just use the same definition we used before. So if we say altStringMessage of a nonempty string, we should get the same thing we got before. Aha, there's a typo, isn't there? Let's fix that. Oh, I think we're gonna get an error here, though. This is good. So we actually just wanna get rid of let. So this is a slight difference. Is nonempty. This wasn't intentional. This is a happy accident 'cause it shows us that we have to do something slightly different. We can't just do exactly the same thing we did before. Before with the string message, we could just call function again, but here, remember, if we use let twice on the same variable name, we get an error. This is this. It's an empty string. And then closing braces. Oops. Oops, and here I forgot the if statement. I'm gonna leave this stuff in 'cause this really happens all the time. I think it's important to know that even experienced developers make this sort of mistake. Okay, up arrow. This is our else. You can also see how cumbersome it is to use the REBL. Okay, so we'll see if this works. I'll just scroll up here, copy this. All right, this string is nonempty. Let me do this here. And the same thing. I don't find the fat arrow notation as intuitive as using function, but as I mentioned, it is in common enough use that you do have to know how to use it, and we'll also see in the chapter on functional programming how the fat arrow notation can give us a really nice compact way of defining functions on the fly.