Terse JavaScript 101 – part 1
by James
at 2011-10-19 05:23:00
original http://james.padolsey.com/javascript/terse-javascript-101-part-1/
While some folk will argue that verbose code aids readability, I think almost the opposite, and in this post I’m going to list some basic tips for minimising redundant clutter in your code. JavaScript is a fun language at its core — it’s worth learning the tiny details.
I hope this post is useful to someone. I wrote it not for beginners (although it will be helpful to them), but for all those people writing JavaScript on a daily basis yet haven’t been afforded the time/motivation to get to know the language properly.
new Object()
Nope, don’t do this:
var o = new Object();
Or any of this:
var a = new Array(); var b = new Object(); var c = new RegExp("1(.)3");
Do this instead:
var a = []; var b = {}; var c = /1(.)3/;
Array literal, object literal, regular expression literal. They rock. There’s usually no need to use the constructor functions when literals are available (please see the note below though).
Note: There are situations when calling Array
or RegExp
directly can be useful. In such situations, you needn’t bother with the new
operator. Array(1,2,3)
will produce the same as new Array(1,2,3)
. Calling RegExp
directly can be useful for dynamically building a regular expression from various strings.
Calling a constructor
If you’re not passing any arguments then the parenthesis are not required. E.g.
var a = new Animal();
… and this becomes:
var a = new Animal;
Petty, perhaps. Still worth knowing though.
var;var;var
Quick and easy. Less of this:
var fun = 123; var tun = 456; var run = 789;
And more of this:
var fun = 123, tun = 456, run = 789;
This is why you should use a tab width of FOUR (or 4 spaces).
Undefined & Null
The following is universally true in JavaScript (assuming undefined
hasn’t been mutilated):
undefined == null
“So what?”, you say? Well, it means you can replace this:
if (foo === undefined || foo === null) { //... }
… With this:
if (foo == null) { //... }
If something is ==
to null
then it is either null
or undefined
. Those are the only possible values.
Returning undefined
Not returning something from a function is the same as returning undefined, so you may as well not bother explicitly returning undefined:
function a() {} function b() { return; } function c() { return undefined; } a() === b(); // true b() === c(); // true
Note: you should be careful with the undefined
value as it can be changed. E.g. You can do undefined = true
beforehand. The universe would shatter if you did that though, so please don’t. Many libraries declare an empty (undefined) variable in an enclosed scope, which provides a real undefined
:
(function(){ // My private scope. They can't see me in here. var undef; undef; // => definitely undefined }());
Or, more succinctly:
(function(undef){ undef; // => definitely undefined }()); // <- not passing anything in!
Empty array values
This is entirely legal in JavaScript:
var a = [,,,'foo']; a[3]; // => "foo"
One potential use-case of this was discussed in my recent post, `match.()` trick.
Less blocks, more expressions
I’m sure we’ve all seen something like this before:
function validateFoo(foo) { var regexResult = /^foo+$/.test(foo); if (regexResult) { return true; } return false; }
A cleaner and more sensible solution is this:
function validateFoo(foo) { return /^foo+$/.test(foo); }
No fussing with if
statements and multiple returns. You can do everything within a single return statement.
Another example. We want to create a function that logs a name, specified by the arguments forename
and surname
, but if these arguments aren’t passed then the function should use the default values, “Bob” and “Smith”, respectively:
function printName(forename, surname) { if (forename == null || forename == "") { forename = 'Bob'; } if (surname == null || surname == "") { surname = 'Smith'; } console.log(forename + ' ' + surname); }
This can be condensed to:
function printName(forename, surname) { forename = forename || 'Bob'; surname = surname || 'Smith'; console.log(forename + ' ' + surname); }
Here, we’re using the logical OR operator (||
) to provide a default value (right hand side) if the left hand side evaluates to false. Values that evaluate to false (i.e. “falsey”) are: An empty string (""
), null
, undefined
, 0
and false
.
So, this:
forename = forename || 'Bob'
… is essentially saying: if forename
is a truthy value, then assign forename
to forename
(in other words: don’t do anything), but if it is a falsey value (e.g. an empty string), then assign the string "Bob"
to forename
.
So, our new printName
function will behave like so:
// -- Logged -- printName(); // Bob Smith printName(0, 0); // Bob Smith printName(false, null); // Bob Smith printName('James'); // James Smith printName('', 'Jones'); // Bob Jones printName('Bill', 'Jones'); // Bill Jones
Part 1 [OVER]
That’s it for today. There may be a part two soon enough, depending on how useful this is to readers. I know many of you have surpassed this stage of learning, so sorry for boring you.
Recommended viewing/reading
Seriously, if you’re writing JavaScript as part of your job then you definitely owe it to future maintainers of your code to learning JS properly.
EDIT: Crockford links don’t work. The entire video can be seen on youtube instead.