1. Number Conversions with parseInt()
Using parseInt() you can get a numeric value from a string. The function
accepts a second radix parameter, which is often omitted but shouldn’t be.
The problems occur when the string to parse starts with 0: for example, a
part of a date entered into a form field. Strings that start with 0 are
treated as octal numbers (base 8) in ECMAScript 3; however, this has
changed in ES5. To avoid inconsistency and unexpected results, always
specify the radix parameter:
var month = "06",
year = "09";
month = parseInt(month, 10);
year = parseInt(year, 10);
In this example, if you omit the radix parameter like parseInt(year), the returned value will be 0,
because “09” assumes octal number (as if you did parseInt(year, 8)) and 09 is not a valid digit
in base 8.
Alternative ways to convert a string to a number include:
+"08" // result is 8
Number("08") // 8
These are often faster than parseInt(), because
parseInt(), as the name suggests, parses and doesn’t
simply convert. But if you’re expecting input such as “08 hello”, parseInt() will return a
number, whereas the others will fail with NaN.
2. Coding Conventions
It’s important to establish and follow coding conventions—they make your code
consistent, predictable, and much easier to read and
understand. A new developer joining the team can read through the
conventions and be productive much sooner, understanding the code written
by any other team member.
Many flamewars have been fought in meetings and on mailing lists
over specific aspects of certain coding conventions (for example, the code
indentation—tabs or spaces?). So if you’re the one suggesting the adoption
of conventions in your organization, be prepared to face resistance and
hear different but equally strong opinions. Remember that it’s much more
important to establish and consistently follow a convention, any
convention, than what the exact details of that convention will be.
2.1. Indentation
Code without indentation is impossible to read. The only thing
worse is code with inconsistent indentation, because it looks like it’s
following a convention, but it may have confusing surprises along the
way. It’s important to standardize the use of indentation.
Some developers prefer indentation with tabs, because anyone can
tweak their editor to display the tabs with the individually preferred
number of spaces. Some prefer spaces—usually four. It doesn’t matter as
long as everyone in the team follows the same convention. This book, for
example, uses four-space indentation, which is also the default in
JSLint.
And what should you indent? The rule is simple—anything within
curly braces. This means the bodies of functions, loops (do, while,
for, for-in), ifs, switches, and object properties in the object
literal notation. The following code shows some examples of using
indentation:
function outer(a, b) {
var c = 1,
d = 2,
inner;
if (a > b) {
inner = function () {
return {
r: c - d
};
};
} else {
inner = function () {
return {
r: c + d
};
};
}
return inner;
}
2.2. Curly BracesCurly braces should always be used, even in cases when they are
optional. Technically, if you have only one statement in an if or a for, curly braces are not required, but you
should always use them anyway. It makes the code more consistent and
easier to update.
Imagine you have a for loop
with one statement only. You could omit the braces and there will be no
syntax error:
// bad practice
for (var i = 0; i < 10; i += 1)
alert(i);
But what if, later on, you add another line in the body of the
loop?
// bad practice
for (var i = 0; i < 10; i += 1)
alert(i);
alert(i + " is " + (i % 2 ? "odd" : "even"));
The second alert is outside the
loop although the indentation may trick you. The best thing to do in the
long run is to always use the braces, even for one-line blocks:
// better
for (var i = 0; i < 10; i += 1) {
alert(i);
}
Similarly for if
conditions:
// bad
if (true)
alert(1);
else
alert(2);
// better
if (true) {
alert(1);
} else {
alert(2);
}
2.3. Opening Brace Location
Developers also tend to have preferences about where the opening
curly brace should be—on the same line or on the following line?
if (true) {
alert("It's TRUE!");
}
Or:
if (true)
{
alert("It's TRUE!");
}
In this specific example, it’s a matter of preference, but there
are cases in which the program might behave differently depending on
where the brace is. This is because of the semicolon insertion
mechanism—JavaScript is not picky when you choose not to end
your lines properly with a semicolon and adds it for you. This behavior
can cause troubles when a function returns an object literal and the
opening brace is on the next line:
// warning: unexpected return value
function func() {
return
{
name: "Batman"
};
}
If you expect this function to return an object with a name property, you’ll be surprised. Because of
the implied semicolons, the function returns undefined. The preceding code is equivalent to
this one:
// warning: unexpected return value
function func() {
return undefined;
// unreachable code follows...
{
name: "Batman"
};
}
In conclusion, always use curly braces and always put the opening
one on the same line as the previous statement:
function func() {
return {
name: "Batman"
};
}
Note: A note on semicolons: Just like with the curly braces, you
should always use semicolons, even when they are
implied by the JavaScript parsers. This not only
promotes discipline and a more rigorous approach to the code but also
helps resolve ambiguities, as the previous example showed.
2.4. White Space
The use of white space can also contribute to improved readability
and consistency of the code. In written English sentences you use
intervals after commas and periods. In JavaScript you follow the same
logic and add intervals after list-like expressions (equivalent to
commas) and end-of-statements (equivalent to completing a
“thought”).
Good places to use a white space
include:
After the semicolons that separate the parts of a for loop: for example, for (var i = 0; i < 10; i += 1)
{...}
Initializing multiple variables (i and max) in a for loop: for
(var i = 0, max = 10; i < max; i += 1) {...}
After the commas that delimit array items: var a = [1, 2, 3];
After commas in object properties and after colons that divide
property names and their values: var o =
{a: 1, b: 2};
Delimiting function arguments: myFunc(a, b, c)
Before the curly braces in function declarations: function myFunc() {}
After function in anonymous
function expressions: var myFunc = function
() {};
Another good use for white space is to separate all operators and
their operands with spaces, which basically means use a space before and
after +, -, *,
=, <, >,
<=, >=, ===,
!==, &&, ||, +=, and
so on:
// generous and consistent spacing
// makes the code easier to read
// allowing it to "breathe"
var d = 0,
a = b + 1;
if (a && b && c) {
d = a % c;
a += d;
}
// antipattern
// missing or inconsistent spaces
// make the code confusing
var d= 0,
a =b+1;
if (a&& b&&c) {
d=a %c;
a+= d;
}
And a final note about white space—curly braces spacing. It’s good
to use a space:
Before opening curly braces ({) in functions, if-else cases, loops, and object
literals
Between the closing curly brace (}) and else or while
A case against liberal use of white space might be that it could
increase the file size, but minification (discussed later in the
chapter) takes care of this issue.
Note: An often-overlooked aspect of code readability is the use of
vertical white space. You can use blank lines to separate units of
code, just as paragraphs are used in literature to separate
ideas.
3. Naming Conventions
Another way to make your code more predictable and maintainable is to
adopt naming conventions. That means choosing names for your variables and
functions in a consistent manner.
Below are some naming convention suggestions that you can adopt
as-is or tweak to your liking. Again, having a convention and following it
consistently is much more important than what that convention actually
is.
3.1. Capitalizing Constructors
JavaScript doesn’t have classes but has constructor functions invoked with new:
var adam = new Person();
Because constructors are still just functions, it helps if you can tell, just by looking at a
function name, whether it was supposed to behave as a constructor or as
a normal function.
Naming constructors with a capital first letter provides that
hint. Using lowercase for functions and methods indicates that they are
not supposed to be called with new:
function MyConstructor() {...}
function myFunction() {...}
In the next chapter there are some patterns that enable you to
programmatically force your constructors to behave like constructors,
but simply following the naming convention is helpful in itself, at
least for programmers reading the source code.
3.2. Separating Words
When you have multiple words in a variable or a function name, it’s a good idea to follow a
convention as to how the words will be separated. A common convention is
to use the so-called camel case. Following the camel case
convention, you type the words in lowercase, only capitalizing the first
letter in each word.
For your constructors, you can use upper camel
case, as in MyConstructor(), and for function and method
names, you can use lower camel case, as in myFunction(), calculateArea() and getFirstName().
And what about variables that are not functions? Developers
commonly use lower camel case for variable names, but another good idea
is to use all lowercase words delimited by an underscore: for example,
first_name, favorite_bands, and old_company_name. This notation helps you visually
distinguish between functions and all other identifiers—primitives and
objects.
ECMAScript uses camel case for both methods and properties, although
the multiword property names are rare (lastIndex and ignoreCase properties of regular expression
objects).
3.3. Other Naming Patterns
Sometimes developers use a naming convention to make up or
substitute language features.
For example, there is no way to define constants in JavaScript
(although there are some built-in such as Number.MAX_VALUE), so developers have adopted
the convention of using all-caps for naming variables that shouldn’t
change values during the life of the program, like:
// precious constants, please don't touch
var PI = 3.14,
MAX_WIDTH = 800;
There’s another convention that competes for the use of all caps:
using capital letters for names of global variables. Naming globals with
all caps can reinforce the practice of minimizing their number and can
make them easily distinguishable.
Another case of using a convention to mimic functionality is the
private members convention. Although you can implement true privacy in
JavaScript, sometimes developers find it easier to just use an
underscore prefix to denote a private method or property. Consider the
following example:
var person = {
getName: function () {
return this._getFirst() + ' ' + this._getLast();
},
_getFirst: function () {
// ...
},
_getLast: function () {
// ...
}
};
In this example getName() is
meant to be a public method, part of the stable API, whereas _getFirst() and _getLast() are meant to be private. They are
still normal public methods, but using the underscore prefix warns the
users of the person object that these
methods are not guaranteed to work in the next release and shouldn’t be
used directly. Note that JSLint will complain about the underscore
prefixes, unless you set the option nomen:
false.
Following are some varieties to the _private convention:
Using a trailing underscore to mean private, as in name_ and getElements_()
Using one underscore prefix for _protected properties and two for __private properties
In Firefox some internal properties not technically part of
the language are available, and they are named with a two
underscores prefix and a two underscore suffix, such as __proto__ and __parent__