Gracefully handling corner cases is the key to writing more robust, error-free JavaScript.
If you work with JavaScript for a living, you write functions. There is just no way around this. So, if you write functions, then arguments are a part of your life. Now, if you are the only one who uses the JavaScript code you write, then life is pretty grand. But if you are writing code that will be consumed by others, then gracefully handling corner cases and errors becomes important; very important.
So, every time I write a function, I assume that someone else will call it. Even if I know no one will, I assume that someday, someway, someone will. Even if it never happens, I feel its a good habit to get into: write code that fails gracefully.
There are a zillion paths down which this conversation can go, but let’s focus on function arguments. When your function absolutely depends on an argument, and that this argument be of a certain type, and that it not be empty, or otherwise useless, you might have a recipe for disaster, if your hungry little function does not get what it needs.
Example # 1A
1 2 3 4 5 |
function someFunc(arg){ if (arg){ //proceed with whatever we need to do }; }; |
Example # 1B
1 2 3 4 5 6 7 8 9 |
function someFunc(arg){ if (arg){ //let’s pretend there is //a whole lot of code here //20 or 30 lines of code //that’s a lot of code to have wrapped //inside of an if() block }; }; |
In Example # 1A, we use an IF () block to make sure that the “arg” argument was passed-in before we attempt to do anything with it.
Good enough, right?
Not so fast…
Even though we have taken care to make sure we got the “arg” argument, what if our implementation code is a bit lengthy? Well, in Example # 1B we see how silly it is for all that implementation code to be wrapped in an IF () block. This kind of pattern breeds code that is annoying to maintain.
Example # 2
1 2 3 4 5 6 7 8 |
function someFunc(arg){ if ( !arg ){ return }; //now we can have lots and lots and lots //of code here //and it’s not wrapped up inside of that //silly if() block }; |
Ahhhhh, now that’s better!
So, as you can see in Example # 2, we simply say: “hey, if arg does not exist, then return.” This was accomplished using the JavaScript logical NOT operator. So, this means that if the argument “arg” does not exist, the function ends right there and none of the implementation code that follows is ever executed.
But…..
What if we need to be 100% sure that the argument “arg” is what we need it to be? What if it’s not enough to simply know that “arg” exists? What if we need to know that “arg” is an array and it has at least one element?
So many questions, so many darned questions.
Example # 3
1 2 3 4 5 6 7 8 |
function someFunc(someArray){ if ( !someArray || !someArray instanceof Array || !someArray.length ){ return }; //now we can safely assume that //we did get an array as an argument //and it’s really an array with at least one element //and we can do awesome stuff with that array }; |
Ahhhhh… that’s even better! In Example # 3 we’ve once again used the JavaScript logical NOT operator to say the following: “hey, if the argument someArray was not passed, OR if it is NOT an array, OR if it does NOT have at least one element, return.” This way, we can check for all the details we need in one neat little line and avoid a series of messy nested IF () blocks. We do our test, we feel good if none of the expressions evaluated to false, and then we proceed with confidence.
Summary
In this article we discussed function argument validation. We learned how to avoid wrapping our code inside of a large IF() block and validate the presence of the argument we need in one line. We also discussed how to test for the type of our argument, and the fact that it contains the minimum amount of data.
Helpful Links for the JavaScript Logical NOT Operator
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Logical_Operators
http://msdn.microsoft.com/en-us/library/ie/zz722703(v=vs.94).aspx