A JavaScript tip that’s jarring: remove falsy elements from array

Elijah Manor tweeted a link today for learnjs, a reader-supported site that provides tutorial videos on writing JavaScript. A pretty good resource to have to be sure, but there was one video there that brought me up short.

The video describes how to filter falsy values (false, null, undefined, 0, NaN, the empty string) from an array. No problem with that but it uses the Boolean constructor in order to do it. Here’s the equivalent code from the video (and from another site I found that espouses this tip), so you don’t have to watch it:

var sourceArray = [false, true, null, { a: false }, undefined, 0, 42, NaN, "false", ""];
var filteredArray = sourceArray.filter(Boolean);
console.log(filteredArray); // prints [true, Object { a=false }, 42, "false"]

The first thing to point out is that the filter function is from JavaScript 1.6 or later (or ECMA-262 5th Edition), so is not present in all browsers. In particular it’s not available in IE8 or earlier (I haven’t downloaded IE9 yet). So this tip won’t work in what’s arguably the most popular browser on end-users’ machines. The Mozilla Dev Network (MDN) defines a function that  you can use to add a compatible Array.prototype.filter function to those browsers that don’t support it. It’s on the page that describes the filter function.

Now onto the thing that really gave me pause: the use of the Boolean constructor function as a normal function. One of the biggest hazards of using constructor functions is that there’s nothing in the language that enforces their use with the new keyword. You can in fact use them as normal functions with nary a warning from the interpreter. What happens when you do? Well, ignoring the built-in constructors (like Boolean, String, Date, etc, which are part of the interpreter’s run-time), unless the writer of the constructor went to great pains to cater for the case of calling the constructor as a normal function, the this variable inside the function will point to the global window object. You could be clobbering essential members of the global object. You could be adding global functions and variables. All bad things.

Hence the universal recommendation or convention that (1) constructors are named with an initial capital letter and normal functions with an initial lowercase letter, and (2) you never use constructors as normal functions. The convention is there to trigger a subconscious warning (since the interpreter won’t give you an actual one) as you use constructors: it’s got an initial uppercase letter so I must use new.

So, although the tip is cool (in the sense of using the minimal number of keystrokes to get something done), there’s no way I’ll be using it. It just looks wrong to me (what’s that constructor doing in there?). I’d use:

var filteredArray = sourceArray.filter(function (x) { return !!x; });

Although I’d admit that double-bang pattern is a little jarring the first time you see it (the right ! operator coerces the operand to a boolean value of the wrong sense, so the left one converts the result to the sense we want). However it’s not as jarring as using a constructor as a function.

Album cover for Piano WorksNow playing:
Armstrong, Craig - Weather Storm
(from Piano Works)


Loading similar posts...   Loading links to posts on similar topics...

No Responses

Feel free to add a comment...

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response