I have a love-hate relationship with JavaScript. I love the language, but I hate the idiosyncrasies. And like many others, I use MDN pretty regularly to verify function signatures, browser support, or to find example code or shims.
The recently posted article on MDN, “A re-introduction to JavaScript”, demonstrates something I wish JavaScript developers would stop demonstrating: cleverness. The article links to one of Crockford’s posts about JavaScript being the most misunderstood language. Sure, there are quirks, but they’re defined quirks in most cases.
I showed a coworker an example of an oddity in JavaScript the other day.
var x = "016";
var y = 0|x;
console.log(y);
// 16
var x = "0o16";
var y = 0|x;
console.log(y);
// 14
console.log(016);
// 14
console.log(0o16);
// 14
This example works differently in ECMAScript 3 and ECMAScript 5, as beautifully explained by CMS on StackOverflow.
Those are ‘gotchas’ of the language that you just have to know. Yes, it sucks. The big problem is when people share code that attempts to be ‘faster’ or ‘more efficient’. Not only do JavaScript developers have to weed out unexpected behavior from the language, but they also have to be diligent to not assume every other JavaScript developer is sharing bug-free code.
This is what you’d see if you were skimming through the recent re-introduction article:
If you’re in a hurry, you’ll probably not see the important bit of text immediately following the examples:
Here we are setting up two variables. The assignment in the middle part of the for loop is also tested for truthfulness — if it succeeds, the loop continues. Since i is incremented each time, items from the array will be assigned to item in sequential order. The loop stops when a “falsy” item is found (such as undefined).
Note that this trick should only be used for arrays which you know do not contain “falsy” values (arrays of objects or DOM nodes for example). If you are iterating over numeric data that might include a 0 or string data that might include the empty string you should use the i, len idiom instead.
If you’re like me and skimming the article for anything interesting, you’ll have probably also missed the text but immediately caught the possible bugginess of the “nicer idiom”. A less experienced skimmer will see the “nicer idiom”, think it’s clever, and use it somewhere it shouldn’t be used. That’s just how the JavaScript community works, even when code on a trusted website like MDN doesn’t work in a given situation.
For a clear example of the problem, consider this code that uses the “nicer idiom” in the wrong way:
// Correction on Mozilla's 're-introduction'
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
var arr = [],
terminate = 20,
i = 0;
while(i <= terminate){
arr[i] = i++;
}
delete arr[5];
// NOTE: arr[0] is 0, which is falsey. This won't print!!!
// change idx=1 and this terminates at index 5.
for (var idx = 0, item; item = arr[idx++];) {
console.log(item);
}
/*
// proper iteration
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
console.log(item);
}
*/
The issue here is that the array must not contain falsy values. This includes undefined values in sparse arrays, null, zero, "0"
, "0.0"
, ""
, NaN
, document.all
, or any other values that coerce to false. The proper way to iterate over an array is to explicitly visit every index unless you have a clearly defined and documented reason not to continue through the array.
The lesson to learn here is twofold: actually read documentation and articles, and don’t just assume JavaScript code is usable code.