Insignificantish whitespace

Whitespace in JavaScript is insignificant. Well, except where it is significant. As you might imagine this makes white space one of the JavaScript common pitfalls.

When I say whitespace, here I'm mostly talking about line breaks. The other whitespace characters are less tricky to deal with. New lines give you a real sense of a break in visual flow, like something new is starting and the old thing is over. In JS this is only sometimes true. Usually in the least helpful situations.

// broken var add = function (a, b) { return a + b } // Innocent comma separated numbers // sitting here for no reason. (1, 2) console.log(add) // 3

Well, not so innocent after all. Those parens actually call the function expression above, assigning 3 to the variable 'add'. The whitespace and comments in-between don't stand in the way. To fix this you need a semicolon somewhere in the middle. The traditional c inspired syntax would have it at the end of the line after the function expression, but it is a fairly common JavaScript style to have it at the beginning of the line before the `(`.

I'm not going to make a value judgment here on which is better. It's possible to choose because of JavaScript's 'automatic semicolon insertion' which is a unique feature that if javascript encounters a syntax error, it backs up to the new line, and tries again as if it had a semicolon there. This mechanism is standardized, and consistent across platforms.

The other type of whitespace that can bite us bad is white space that looks insignificant but actually turns out to be significant.

console.log( get('foo')({foo: 'bar'}) ) // broken function get (property) { return function getter (obj) { return obj[property] } }

This is a common function i write all the time, it takes the name of a property, and returns a getter function that returns the value of that property on any objects it's handed. But this one has a subtle error.

For some reason, while new lines are almost never significant, they are after a return, if what follows is valid standing on its own. In this case that means that 'get' returns undefined, and 'getter' is a function statement that is hanging out in the ether never to be referenced again.

console.log( get('foo')({foo: 'bar'}) ) function get (property) { return function getter (obj) { return obj[property] } }

Move that function up a line, and all of a sudden 'getter' is a function expression that gets returned by 'get' and used to access 'bar' to be logged.

One way to guard against this is to treat all whitespace as significant and prefixing '(', '[' and unary usage of operators that can also be binary operators with a ';' at the start of the line. Kind of a nuclear option, but it has other benefits too. The other way is to always wrap multi line returns in parens, with the opening paren on the same line as the return. That open paren forces it to not magically treat a new line significantly.