Skip to content

Code And Cognitive Load

KISS: Keep It Simple (and) Stupid - Writing code for humans. This post explains why I believe using constructs like ~"a".indexOf("b") is a bad practice.

You know what ~"a".indexOf("b") does, right? Oh, you don't? Well, that expression is truthy when "b" is present in "a". The following constructs accomplish the same task:

if (~"a".indexOf("b")) {
  // do something

if ("a".indexOf("b") > -1) {
  // do something

In the latter example you merely need to know that indexOf returns -1 if the needle ("b") could not be found in the haystack ("a"). If you don't know this already, you can look it up easily in the docs. You're only a google of mdn string indexOf away from enlightenment.

The former example is a bit more tricky. Let's assume you don't know that ~ is the bitwise NOT operator. You google for mdn javascript ~ and find nothing immediately useful. You realize that ~ is an operator and refine your query to mdn javascript operators. Once you've landed on the Operators overview, an in-browser search for ~ leads you straight to the bitwise operators. Great! You now know that ~ "Inverts the bits of its operand". If you read the sectiont Signed 32-bit integers you'll also learn that »Two's complement format means that a number's negative counterpart (e.g. 5 vs. -5) is all the number's bits inverted (bitwise NOT of the number, a.k.a. one's complement of the number) plus one.«. You're probably not satisfied by that just yet, so you google on and eventually land on Wikipedia's Two's Complement. Here, for the first time, you see the following table:

decimal: binary representation
      2: 0000 0010
      1: 0000 0001
      0: 0000 0000
     -1: 1111 1111
     -2: 1111 1110

It is only now that it dawns on you that ~(-1) === 0 and ~(0) === -1. Now add the fact that any number that is not 0 is truthy, and you've understood an expression that saves you typing 2 characters (4, if you count spaces).

Having spent a bit of time at a university, I was bullied into manually decoding all sorts of binary representations - Two's Complement being one of the simplest. Not everyone has had this pleasure. Not everyone has had to decode binary data in their past. At least most frontend developers I know haven't. Heck, I still don't need any bitwise operators for my day job.

Aside from the fact that ~"a".indexOf("b") requires a higher cognitive load than "a".indexOf("b") > -1 there's no difference in performance. So why bother with trickery like this at all?

I didn't think of this as a big deal until I started asking random devs (over lunch) if they knew what ~ did and how the indexOf() trick works. One out of ten knew the whole story. Three out of ten understood once I said "Bitwise Not and Two's Complement" (naming, not explaining). The other six out of ten didn't know what was happening. None had less than 3 years experience.

Update (October 7th 2013)

This post focused on using ~ in conjunction with indexOf() - but there are a great many more operator abuses out there. Another nifty one is ~~123.5, which does the same as Math.floor(123.5) - implicitly casting a Number to int. Please. Never. Write. Code. Like. That.

Of course I've gotten feedback (on twitter) along the lines of »If they [novice developers] don't understand what's going on, they need to learn it!« Well, yes. Obviously they should learn this stuff. That is not a question, really. In question is the (perceived) arrogance of developers writing code that is not easily understood by their peers. Programming is tough enough as it is, we really don't need to make it harder by obfuscating what our code does.


Display comments as Linear | Threaded

No comments

The author does not allow comments to this entry