Pop quiz, hotshot, the image shows a common JavaScript ‘gotcha’ – or inadvertent mistake through incomplete knowledge of something. What exactly is happening here?
You create a simple function called “getPerson”, and it returns you a JSON object with a single property on it, “name”. However! When you come to use the “name” property, it is undefined.
How come?
The Amazing Solution!
I prepared this gotcha after a lunchtime discussion with some colleagues turned to the “Python” programming language (yes, we’re geeks, get over it).
One chap made a derogatory comment of Python, something like, “what kind of a programming language uses white-space as flow control?!”
The irony is, ubiquitous JavaScript is happy to use whitespace as flow control too…
JavaScript Uses Whitespace as Flow Control? What on earth are you on about, Richard? You lunatic.
It’s true! The problem with the code above is where the curly brace ‘{‘ is placed after the return statement.
JavaScript Gotcha!
Wrong:
<!DOCTYPE html> <html> <head> <title>JavaScript Gotchas 1</title> </head> <body> <script type="text/javascript"> var getPerson = function () { return { name: "Bob" }; } alert(getPerson().name); </script> </body> </html>
Right:
<!DOCTYPE html> <html> <head> <title>JavaScript Gotchas 1</title> </head> <body> <script type="text/javascript"> var getPerson = function () { return { name: "Bob" }; } alert(getPerson().name); </script> </body> </html>
As JavaScript doesn’t require you to define the return type of a function (like C# does, for example), you can just simply call “return” at any point and it will end the execution of the function. This is the important part: Semi-colons in JavaScript are sometimes optional! And calling return is one of those cases!
From the JavaScript parser’s point of view, you’ve simply called “return” and then put a line break (return key on your keyboard). The parser assumes you want to return then and there and ends execution. It DOESN’T go looking around on the following lines to see if you’ve specified something to actually return!
So in-fact, the above call to “getPerson()” returns you “undefined”, and “undefined” doesn’t have anything on it called ‘name’.
Bottom line: JavaScript uses whitespace as flow control!
Mitigation
You can stop this from happening by always ensuring your curly braces go on the same line as the return statement (as above in the “Right” code example). In fact, in JavaScript you should always try to write your code with the curly brace on the same line as the statement that prefixes it. It’s the “One True Brace Style” after all. (Although I prefer Eric Allman indentation for everything that isn’t JavaScript).
if (expression) { // do something }
for(var i = 0; i < myArray.length; i++){ // Enumerate myArray }
Etc. Etc. Etc.
In the next “Common JavaScript Gotchas” article, I will be delving into the murky depths of Type Coercion! (I bet you’re salivating at the thought.)