JS Adolescence: Change of opinion regarding certain JavaScript practices
james.padolsey.com
james.padolsey.com
Object literals are one of the best features of Javascript, learn to love them. In the example cited, you already have a function dedicated to creating this object; why would you need to further obfuscate it by delegating the actual leg work to a buzzword-filled framework (or worse, vanilla constructors)? Even for more complex examples, I find it clearer and simpler to use an extend() or clone() method than something that tries to emulate classes.
Strict equality everywhere:
You cherry-picked two simple examples, but normally it's more complex than that. Javascript has rather odd coercion, and it will bite you if you try to memorize all the cases where it's safe to use ==. It's not really that === is "strict", it's just that it generally works how == was supposed to. More importantly, though, there's never any harm in using === instead of ==, so why would you use the latter? Why is === "overkill?" Because it's one character more? I fail to see the argument for not using it, except to play the devil's advocate.
Strict coherence to a standard:
This is a fine swing to take if you're doing hobby work, in fact it's very healthy, but if you're working on any sort of larger project where you are or will be collaborating with others, it is nothing short of essential to agree on standards for everything from brace style to camel case to testing frameworks. Almost every other argument concerning style, practices, and idioms falls apart in favor of consistency.
If you "fail to see the argument for not using it", then you're not trying hard enough.
Javascript was not designed with strict equality check in mind. The coercion it does can be harmful if you don't know how it works, but it can be very useful and liberating if you do.
Essentially, but restricting yourself to "strict equality" you make Javascript a less dynamic language. Sometimes "20" is as good as 20.
Dimitry Baranovsky, of Raphael fame, wrote about this specific issue:
Why is this on the front page?
He does offer explanations (e.g, related to anonymous inline regular expressions that they cannot be cached and that they don't easily convey their purpose like a name would).
Plus, whether he offers explanations or not is beside the point. It's a blog post, not a published paper, and as such it can serve to get the ball rolling. Which it did, judging from the discussion here.
It's also just bad form because of how people write Javascript, for example if you have an unfortunately long nested function with a variable declaration toward the bottom with a common name, say 'width' and later add that variable name a level up in scope and then think to use it in your function because you forgot or didn't know you had a var statement declaring width somewhere in that function you'll have fun staring into the abyss when this runtime error eventually presents itself.
While I acknowledge that declaring vars within ifs/whiles and such can lead to misunderstanding, declaring vars close to the site of first use at the top-level block of a function has never resulted in a bug for me. This approach also diffs better.
Mainly because I suck at it (I'm a designer, not a developer, dagnabbit) and it helps me keep track of what I'm doing.
Other than that, great article, taught me a thing or two.
The more descriptive your naming, the better your design and the less comments you require.
if (!cachedReturnValues[key]) { cachedReturnValues[key] = value; }
cachedReturnValues[key] === false
cachedReturnValues[key] === 0
cachedReturnValues[key] === ""
cachedReturnValues[key] === null
cachedReturnValues[key] === undefined (this is presumably the only desired behaviour)
cachedReturnValues[key] === NaNThen this kind of code would have blown in your face.
Besides the function being re-evaluated, the hash gets a NEW value "value" for that key. Nobody ensures that "value" is the same as the one it was already there.
E.g
var cachedReturnValues = {key: 0};
var value = 50;
if (!cachedReturnValues[key]) { cachedReturnValues[key] = value; }
So, instead of setting the value when the key is not already in the hash, now we also CHANGE it in all these false-positive cases.
Furthermore, even if (a) the function had no side-effects, and (b) by some magic the value was the same with what was already in the hash, e.g if your wrong "merely re-evaluation" assumption was true, who would ensure that the overall block has no side-effects?
if (!cachedReturnValues[key]) { cachedReturnValues[key] = value; doSomethingElse(); }
Just because we see it written in a way that doesn't do much harm now, doesn't mean it's not extremely dangerous to blow up in the future, e.g. when some naive programmer adds another statement to the block.