“Effective JavaScript”, a Review

David Herman’s book “Effective JavaScript” is written for developers who are already comfortable with basic JavaScript syntax and semantics, but want to learn the idioms (he calls it “pragmatics”) of the language. There’s an old saying, “You can write FORTRAN in any language,” meaning that developers who learn the best practices of one (possibly older) platform may not update their style with a newer platform and may simply to continue to code in the older style in a more (or differently) capable language.

Egregious examples of this weakness include non-object oriented style in C++ or non-functional style in C#. As an experienced C# developer who writes enough JavaScript to get by, and no more, I often worry that I’m “writing C# in JavaScript” (see also “How Good C# Habits can Encourage Bad JavaScript Habits“). Herman writes his book to developers in a similar situation.

The book is divided into a series of items, where each item addresses one facet of JavaScript that might be misunderstand, misused, or unknown to a developer inexperienced in JavaScript.

Most Interesting Items

Coming from C#, I found several items to be particularly valuable:

Item 13: Use Immediately Invoked Function Expressions to Create Local Scopes

In C# there are (somewhat rare) occasions where a variable needs to be declared inside a loop to avoid an incorrect reference. In JavaScript, however, two language features that conspire to make this difficulty substantially more dangerous: all “outer” variables are stored by reference in the closure, not by value; and JavaScript does not support block scoping. In other words, you can’t have a value type, and you can’t declare a local variable scoped inside a loop (or other block).

Since functions are the only scoping type in JavaScript, a workaround is to create and immediately execute a function to enclose the scope.

Item 18: Understand the Difference between Function, Method, and Constructor Calls

In C#, classes (as opposed to objects) are a real distinction, and a constructor is a specific “kind” of thing with special compiler treatment. In JavaScript, it becomes clear through exposure that functions can serve as classes (that is, be instantiated with “new”) but many of the subtleties are unclear. When is a function also a constructor? Since there are no classes, only functions and objects, what does “new” actually do? This item helps clear up some of these confusions.

There’s a lot that isn’t answered by this “item”, but that alludes to be answered to by future items (mostly in Chapter 4, “Objects and Prototypes”)

Item 21: Use apply to Call Functions with Different Numbers of Arguments

In C#, methods usually have a fixed number of parameters. A method can be made to accept variable parameters using a params array. Consider the String.Format method:

public static string Format(
	string format,
	params Object[] args
)

Such a method could then be called either with an actual array or with variable parameters. The “work” of allowing this flexibility is done by the method definition, in the use of the “params” keyword.

String.Format("{0} - {1} - {2}", someArrayOfThreeObjects);
// OR
String.Format("{0} - {1} - {2}", object1, object2, object3);

In JavaScript, the same capability exists, but this work is instead done by the caller using the “apply” syntax. An interesting comparison.

Item 36: Store Instance State Only on Instance Objects

What the author here shows as an “accident” could easily be reclassified as the JavaScript distinction between static and instance members. Instance members go on the instance. Static members go on the prototype. I suppose the distinction is only equivalent for fields/properties, not for methods.

Item 49: Prefer for Loops to for…in Loops for Array Iteration

C# programmers are very accustomed to using foreach loops for iterating over the items in a collection (such as an array). This naturally leads to the temptation to use the similar-seeming for…in loop in JavaScript to iterate over an array. Bad plan. Use .forEach method on arrays instead (in ES5).

Concurrency

The final chapter is on concurrency. Overall, this section made me appreciate the .NET Task Parallel Library and C#’s async/await so much more. It is also effectively exposed the dangers of trying to handle concurrency “on your own” without using appropriate high-level constructs.

Overall

An excellent review of JavaScript “gotcha’s” and best practices that might not be obvious to a developer approaching from another language, such as C# or Java. It’s a short book, a quick read, but worthwhile.