21

I have read Crockford's JavaScript: The Good Parts and have used his validator JSLint. I am sometimes left wondering the justification behind his recommendations. Below is a list of examples I want substantiated.


  1. Why does JSLint signal an error if you don't include "use strict";? [See this SO thread.]

  2. Why should variable declarations within a function be done using a single var? [See this SO thread.]

  3. Why do we need to put a space between function and () in function ()?

  4. Why can't we use continue?

  5. What is wrong with ++ and --?

  6. Why can't we use the comma operator , (except in the initialisation and incrementation parts of the for statement)? [See this blog post.]

  7. Why should every single statement end with ;? [See this blog post.]

Community
  • 1
  • 1
Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • 3
    This probably should be on http://programmers.stackexchange.com/ – OverZealous Aug 05 '11 at 02:02
  • 4
    I respect Mr. Crockford, and agree with quite a few of his opinions about JavaScript practices (if not all of them), but I think in some cases his justification falls into the "Because I said so" category. – nnnnnn Aug 05 '11 at 02:10
  • this question would be more constructive and less contentious if you included specific examples – Darko Aug 05 '11 at 02:13
  • 1
    @c4757p: Yes, JavaScript does have some good parts. – icktoofay Aug 05 '11 at 02:49
  • 1
    Thats some good questions, voting to reopen. I'd love to hear the reasoning behind some of those assertions – Darko Aug 05 '11 at 03:48
  • I've read this several times, and I can't quite decide if it meets the 'good subjective / bad subjective' criteria. As such, I'm not casting a super vote to re-open this, but I will point out that it has four re-open votes from the community. For now, I'm making this question CW. Please note, this doesn't at all imply that I feel this is a good fit for SO, but I'm not really sure that it _isn't_, so I'm taking the minimal amount of action needed based on how the community is voting. – Tim Post Aug 05 '11 at 05:35
  • @OverZealous - I think this is a bit _too_ 'programming related' to send to Programmer's SE (oh, the irony in that statement). This really is digging into some assertions regarding JS that could be answered objectively. – Tim Post Aug 05 '11 at 05:38
  • @Randomblue - I was thinking about editing it, but honestly I'm not quite sure how I could while preserving your original intent. Don't get me wrong, I don't think this is a _bad_ question, my only reservations about re-opening it are centered around the strong possibility of extended discussions. [This](http://blog.stackoverflow.com/2010/09/good-subjective-bad-subjective/) is what I mean by the different types of subjective. Please keep in mind I'm not trying to be negative, this question needs only one more vote to be re-opened. – Tim Post Aug 05 '11 at 14:01
  • 1
    I've reopened this question. I would love to have these 7 questions answered (in short) in a CW answer. – Šime Vidas Aug 05 '11 at 15:38
  • @Šime: I'm afraid my answer isn't short, but it could probably be summed up to something like "all of the above can mask programming errors" (quoting Crockford). – Reid Aug 06 '11 at 00:24
  • @Reid No problem. Thank you for the effort `:)` – Šime Vidas Aug 06 '11 at 01:34

2 Answers2

31

Much of the behavior of JSLint is explained on the JSLint instructions page. I will refer to it as the JIP from now on.

Much of the behavior that is not explained by the JIP is explained by Code Conventions for the JavaScript Programming Language by Crockford. I will refer to it as the CCJPL from now on.

To go down the list:

1) Why does JSLint signal an error if you don't include "use strict";?

Because strict mode enforces many good practices; JSLint is all about enforcing good practices too, so naturally this is its behavior. Looking at what "use strict" enables helps clarify the matter. I'm simply going down the list of this blog post by Resig, so due credit is given there. I'm not commenting on everything it does because I'm not sure of exact reasoning from Crockford for every feature.

  1. Variables must be declared with var before you can assign a value: this stops implicit globals from appearing. Global variables are considered by Crockford to be evil, and this helps eliminate globals you didn't explicitly set.
  2. It several restricts eval, which Crockford considers to be evil as per the JIP.
  3. It disables the with statement. This is considered by Crockford to be harmful.

I only skipped out on two features of strict mode: the delete statement's behavior being modified and overwriting the arguments variable. I don't know if Crockford agrees or disagrees with these two things, but given that he helped create the ECMAScript 5 standard, I would lean towards agree.

2) Why should variable declarations within a function be done using a single var?

First, any variable that is defined without being declared by var is implicitly global, which, according to the JIP, can "mask misspelled names and other problems." So, that is the reasoning requiring var.

As for requiring one var, all variable declarations are hoisted to the top of their scope by the JavaScript engine automatically, so my only guess is that Crockford wishes for the developer to be acutely aware of this behavior. Past that, it's probably a matter of style. Which do you prefer between the two following pieces of code:

var a, b, c;

or

var a; var b; var c;

My guess is that Crockford thinks the multiple vars are ugly there. I agree with him on that point.

Ironically, as per the CCJPL, he actually suggests having all of the variable declarations on different lines with associated comments. JSLint disagrees with him in this regard!

3) Why do we need to put a space between function and () in function ()?

This applies only to anonymous functions. As per the CCJPL, it is because:

If a function literal is anonymous, there should be one space between the word function and the ( (left parenthesis). If the space is omited, then it can appear that the function's name is function, which is an incorrect reading.

When I was in the thick of learning JavaScript, I religiously began following Crockford's conventions... but the logical part of me says that if you have code that names a function function, it's probably in dire need of reworking anyways. (Not to mention that in JavaScript, it's a SyntaxError because function is a keyword.)

4) Why can't we use continue?

To quote the CCJPL:

It tends to obscure the control flow of the function.

Not exactly an elaborate answer, but I've seen arguments on the internet comparing it to goto. Take that as you will.

5) What is wrong with ++ and --?

As is said on the JIP:

The ++ (increment) and -- (decrement) operators have been known to contribute to bad code by encouraging excessive trickiness. They are second only to faulty architecture in enabling to viruses and other security menaces. Also, preincrement/postincrement confusion can produce off-by-one errors that are extremely difficult to diagnose.

6) Why can't we use the comma operator , (except in the initialisation and incrementation parts of the for statement)?

Another elaborate explanation from the JIP:

The comma operator can lead to excessively tricky expressions. It can also mask some programming errors.

This is a real shame, because as the blog post you linked shows, the comma operator can really increase the clarity of code in some situations.

You will notice a common underlying theme throughout many of Crockford's conventions: understandable, readable code. This is just another example of that. Many conventions are centered around denying access to 'tricky' expressions.

But I think the real word I'd use to describe some of these expressions would be 'terse' -- which is not necessarily a bad thing, per se, but it can be evil if used wrongly. Crockford's conventions sometimes try to smash wrongly-used-terseness by removing some of the tools these expressions use, even if they have legitimate uses in some contexts.

7) Why should every single statement end with ;?

To quote the JIP again:

JavaScript uses a C-like syntax which requires the use of semicolons to delimit certain statements. JavaScript attempts to make those semicolons optional with a semicolon insertion mechanism. This is dangerous because it can mask errors.

Like C, JavaScript has ++ and -- and ( operators which can be prefixes or suffixes. The disambiguation is done by the semicolon.

Usually I find the 'can mask errors' part of Crockford's explanations to be rather broad and vague, but semicolon insertion is really one area where I can agree wholeheartedly. It's easier to use explicit semicolons after every statement than risk narrowing the dangerous waters of semicolon insertion.

Here is a classic example of semicolon insertion gone wrong from the Wikipedia page on JavaScript Syntax:

return
a + b;

// Returns undefined. Treated as:
//   return;
//   a + b;

And if you use an object literal like the code from this blog post (a fairly common style of braces), then it can mess you up too:

function shoeFactory() {
    return // <--- semicolon inserted here
    {
        shoeSize: 48
    };
}

var shoe = shoeFactory();
console.log(shoe); // undefined

Another example from the above Wikipedia article:

a = b + c
(d + e).foo()

// Treated as:
//   a = b + c(d + e).foo();

I've never really been perturbed by adding explicit semicolons, either. They come to me very naturally when writing almost any code. In fact, I often catch myself putting semicolons in Python even though they're not necessary.

In this case, I agree pretty wholeheartedly with Crockford. I think one debugging session concerning semicolon insertion would probably convince most people that it would be easier just to place them in the code.

Reid
  • 18,959
  • 5
  • 37
  • 37
  • 1
    I strongly disagree with number 4 and 5. `continue` doesn't obscure anything. It's not JavaScript-specific either, so everybody should be familiar with it. It's usually a nice way to skip the rest of the current iteration. And ++/-- "encouraging excessive trickiness"? And he goes on about enabling viruses?? It's a simple operator. Again, not JS-specific at all. And if someone tends to forget that ++x returns the new value and x++ returns the old value, well just look where the +/- sign is. But he has good advice otherwise. – basic6 Oct 09 '14 at 08:18
12

You're right, Crockford doesn't very often substantiate his practices.

For example, defining vars somewhere other than the top of the scope is fine in my opinion, as long as you're aware. Javascript will hoist them to the top of the scope anyway. Furthermore, I think its actually beneficial, because you can easily pick out the initial value of a variable, all you need to do is look for the var.

I also think switch-case fallthroughs are very beneficial if you know how to use them. Particularly for writing something like a very complex state machine.

if and for's with a single statement following them, without curly braces is also fine. People have been writing C this way for decades.

If you're aware of what constitutes the end of a javascript statement, semicolons aren't necessary either. Semicolon insertion isn't random, it's not undecipherable contrary to popular belief.

Crockford is well known for trashing regex's...which is terrible. Very powerful (and fast) lexers can be written using regex's as the lexemes/rules/grammar/whathaveyou.

For the most part Crockford knows what he's talking about, but don't take his personal style as gospel. It's very unsubstantiated in my opinion. Some of the best javascript coders I've seen are in direct opposition to Crockford's style with regards to their code.

edit: I don't see why this question was closed. It can be discussed objectively, and is worth talking about.

chjj
  • 14,322
  • 3
  • 32
  • 24
  • Could you link to blog posts or other material with recommendations in direct opposition to Crockford's style? – Randomblue Aug 05 '11 at 02:31
  • 1
    To be clear, I didn't mean the coders themselves were vocally in opposition to Crockford, I just meant their particular styles were. But if you want to see someone who advocates the non-use of semicolons for example, you could look at Isaac Schlueter's blog: http://blog.izs.me/ . Isaac is one of the devs for Node.js. – chjj Aug 05 '11 at 02:36
  • 6
    completely agree. the problem with crockford is that he says stuff that is backed by experience with the same authority as stuff that is backed by personal preference, and attacks anyone who disagrees with the same ferocity. The dude is an awesome dev, and the father of modern js, but as someone who disagrees with almost all of his opinions on style, he makes me have to constantly justify myself to people who take his word as gospel. – Matt Briggs Aug 05 '11 at 23:12
  • 1
    @MattBriggs and amen to that! – Alnitak Nov 02 '12 at 15:05
  • 1
    But until someone writes & maintains as handy a tool as JSLint with as solid a set of best practices, there is a practical advantage to taking JSLint's advice (or JSHint's, either with your standardized set of options for your computing cadre). Creating a culture of quality code is not about acknowledging everyone's subjective definition of what's best. The improvement in quality comes from the corporate (in at least two senses) standardization of convention. Say what you will about Crockford; at least it's an ethos. And, objectively speaking, **these suggestions aren't functionally wrong**. – ruffin Apr 04 '13 at 14:03
  • 1
    @ruffin Comparatively, PEP8 has done wonders for Python and the willingness to conform for consistency in code is awesome. Consistency is the key here, not who is actually right, and what is consistently more valuable in more situations should be what is advocated, but it does not have to be. That's not to say "never" break the rules, but to say, if you are sharing the code with a larger audience, try to conform to some greater standard. Try not to over think this, I am talking about code convention for large audiences only, individualism has its place. – Derek Litz Dec 12 '13 at 12:37
  • if goto fail goto fail – Jimmy Bosse Mar 11 '14 at 01:25
  • Use of `if` or `for` with a single statement afterward is visually clear and unambiguous if every close brace on a line by itself is matched by an open-brace which is also on a line by itself. If lines that start with `if` open compound statements, then every `if` needs a close-brace. If multi-line compound statements are only started by lines that contain simply `{`, then control statements which control simple statements will produce no visual ambiguity. Putting `{` at the end of control-statement lines saves a line for a compound-statement `if`, but compels the use of... – supercat Jul 20 '14 at 17:48
  • ...an otherwise-unnecessary `}` line for a single-statement `if`s. Which style is more efficient depends upon whether the majority of `if` statements control one statement, or more than one. Personally, I like the vb.net model, where `If` begins a compound statement [which must be terminated with `End If`] unless the controlled statement follows the `If` on the same line--useful for e.g. `If X>5 Then X=5`. – supercat Jul 20 '14 at 17:51