douglascrockford/JSLint — pull request #160 by waynerad (2014-09-11 20:18:33+00:00)
Title: JSLint will enforce camelCase coding style by disallowing underscores ("...

I've made a version of JSLint that enforces "camelCase" coding style.

Rationale:

When I show code I've written to other JavaScript developers, they've frequently reacted with instant horror upon seeing the underscores. "Don't you know camelCase is THE STANDARD for JavaScript?" they always ask me. I've done Google searches on "underscores vs camelCase" and polled every developer I know to find out their opinion on the issue. Only one programmer, a grizzled C programmer, has told me he likes underscores, and can't get used to camelCase. All the others have either told me underscores look "ugly" and that if I cared at all about the aesthetics of my code, I would make it camelCase (I always thought camelCase looked unaesthetic with the lower case first letter, and then upper case letters later on, but I'm getting used to that bit of weirdness) or that it simply didn't matter whether everyone used underscores or camelCase *as long as everyone does the same thing*.

It also looks to me like the direction the software development world is going, in general, is towards camelCase -- new languages like Go explicitly state that camelCase is the standard (though it is still convention, not actually enforced by the Go compiler), and with older languages like PHP that used to use underscores, almost all the new code written seems to be in camelCase. The biggest holdout seems to be Python, which, due to decree by benevolent dictator Guido Van Rossum, still uses underscores as the standard coding style, and it seems this is only because that is his personal preference and he happens by historical accident to be the benevolent dictator. But all other major languages, and especially Java and JavaScript, seem to use camelCase as their coding style.

So I decided to convert my code to camelCase. At first I pondered doing search-and-replace willy-nilly, but that seemed likely to introduce a lot of errors. I quickly came up with a better way: modify JSLint to throw an error every time it sees an underscore in any token name. I got the source code and hacked together a version that did this. Using this, I was able to convert my code to camelCase, which, while tedious and boring, was entirely error-free.

Since then I have been using my private copy of JSLint to lint all my code including the camelCase requirement. But of course, you have continued to make improvements to the master version of JSLint. So, today, I decided to integrate this feature *properly* into JSLint, so I don't have to continually resyncing your improvements with my private copy, and also to make the change available to all developers.

This seems to be in keeping with the philosophy of JSLint, which enforces *lots* of stylistic conventions. Surprisingly, camelCase is not one of the stylistic conventions that it enforces, even though it appears a well-established standard. However, since it appears to be THE convention for JavaScript and several developers have dinged me and told me they would simply never contribute to my project since it didn't use camelCase, it makes sense to me that JSLint should enforce the camelCase convention also.

The way I did it was to make camelCase enforced by default, but can be disabled by a new option, "Tolerate... _ in identifiers" which appears right under "dangling _ in identifiers" in the UI. In code, enforcement of camelCase can be disabled with

/*jslint undersc: true */

("undersc" indicating to allow underscores).

I modified the JSLint source code itself to include /*jslint undersc: true */ because it looked like JSLint was designed to pass itself. (The JSLint source code uses underscores and not camelCase and I did not convert it! But I did add the directive so it would continue to pass itself.)

It's up to you whether to accept the pull request or not. You can:

- Accept it,
- Accept it and make changes, (for example if you didn't like "undersc" for the directive name -- very simple to just change it to whatever you want -- I chose "undersc" because it seemed to be the JSLint style to give the directive options terse names),
- Demand I make further changes, such as reversing it so underscores are permitted by default (in which case I guess it would have to be moved to the "Assume..." column, more on that below), or
- Do nothing.

The rationale for enforcing camelCase by default is that it seems to be the philosophy of JSLint that JSLint does what makes the most possible sense regardless of whether the changes "break" existing code.

Furthermore since existing code can be grandfathered in with a directive if developers don't want to fix it, (as I did with the JSLint code itself), "breaking" existing code doesn't seem to serious.

Still, I recognize that this is a major change to JSLint as it affects every single identifier name in a program. Making this feature enabled by default would require additional documentation on other pages on the jslint.com site (and possibly warrant a notification on the home page?).

But if it's a big enough issue that JavaScript developers recoil with horror upon seeing my code and tell me they won't contribute to my project if it uses underscores instead of camelCase, and insist it is THE standard for JavaScript ("didn't you ever notice the built-in functions?" -- and it's true, it's not just DOM functions like getElementById but built-in JavaScript functions like charAt and indexOf that are camelCase), then camelCase seems important enough to justify JSLint enforcing by default. My guess is the majority of JavaScript developers are already doing everything in camelCase and their code with pass with few modifications, and they will appreciate the addition of this new check.

Also: I added the /*jslint undersc: true */ directive to ADsafe (one of JSLint's dependencies). So there is a pull request for you for that also, should you choose to accept it.

I validated the change with the following script ("validate" is the directory name where the validation set is assembled):

copy JSLint\JSLint.js validate
copy ADsafe\adsafe.js validate
copy JSON-js\json2.js validate
copy JSLint\intercept.js validate

type validate\jslint.js validate\adsafe.js validate\json2.js validate\intercept.js >> validate\web_jslint.js

copy JSLint\init_ui.js validate

copy JSLint\jslint.html validate
copy JSLint\title.png validate

copy run-jslint\1and1pill.gif validate
copy run-jslint\adsafepill.gif validate
copy run-jslint\github.gif validate
copy run-jslint\jslintpill.gif validate
copy run-jslint\jsonpill.gif validate

and then verified that the feature works, no run-time JavaScript errors occur, and that running web_jslint.js through JSLint itself produced the same errors as before. (It is not actually error free -- it gives 'Redefinition of' and 'Read only' errors.)

I hope this can be merged back into the main version, since I don't want to be continually out of step with the latest improvements to the main version.

P.S. THANK YOU so much for a) creating JSLint, which is a godsend for creating high-quality web code, and b) for making the source code sufficiently comprehensible that a person such as myself who has no background in parsers is able to make a change such as this.