Skip to content

Instantly share code, notes, and snippets.

@webdesserts
Last active December 31, 2015 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webdesserts/7934890 to your computer and use it in GitHub Desktop.
Save webdesserts/7934890 to your computer and use it in GitHub Desktop.
Testing for the presence of an item in an array with `.indexOf()` and the `~` bitwise operator
var desserts = ['gelato', 'tiramisu', 'double chocolate volcano cake']
// indexOf() is a nifty little Array method that returns the index of the element passed
desserts.indexOf('gelato') //=> 0
// One oditty of it is that it returns -1 if there is no match.
desserts.indexOf('meatloaf') //=> -1
// So the question arrises, "why -1"?
// well let's say we want to test if 'gelato' exists in the desserts array.
// normally we would have to do something like this:
var exists = false;
desserts.forEach(function(item) {
if ('gelato' === item) exists = true;
})
// well it turns out we can use this "one weird trick" to do the same thing with indexOf()
// So why doesn't indexOf() return null or something similar?
// Well as we know arrays have 0 based indexes, so if we tried
// to coerce the index to a boolean, the first item of the array
// would always return false.
teramisu = desserts.indexOf('teramisu') //=> 1
Boolean(teramisu) //=> true
gelato = desserts.indexOf('gelato') //=> 0
Boolean(gelato) //=> false
// So unfortunately we wouldn't be able to use the index directly in a conditional
// This is where the bitwise ~ operator comes in.
// ~ is what is known as the "bitwise NOT" operator
// The ~ operator essentially returns -(n+1)
~1 //=> -2
~5 //=> -6
~0 //=> -1
~-5 //=> 4
~-1 //=> 0
// note that last one there. That's the same as...
-(-1+1)
//or
-(0)
// this means that unlike any other number, -1 converts to 0 which so
// happens to be the only number that coerces to false.
// Aha! See where this is going now?
// So let's try using this on our indexOf() results.
Boolean(~desserts.indexOf('gelato')) //=> true
Boolean(~desserts.indexOf('teramisu')) //=> true
Boolean(~desserts.indexOf('meatloaf')) //=> false
// Let's expand that to see what's going on behind the scenes
index = desserts.indexOf('gelato') //=> 0
num = ~index //=> -1 from -(0+1)
Boolean(num) //=> true
index = desserts.indexOf('teramisu') //=> 1
num = ~index //=> -2 from -(1+1)
Boolean(num) //=> true
index = desserts.indexOf('meatloaf') //=> -1
num = ~index //=> 0 from -(-1+1)
Boolean(num) //=> false
// so whenever indexOf() can't find an item in the array, it
// returns -1 which the ~ operator can convert to 0 which is
// coerced to false, while 0 is safely converted to -1 and
// coerced to true.
// This allows simple one liner tests for the existance of an item in an array
if (~desserts.indexOf(item)) eatDessert(item)
// pretty cool, huh?
// For more information on WHY the ~bitwise operator works
// the way it does, I would suggest checking out the MDN article on the ~ operator
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#.7E_(Bitwise_NOT)
// And this talk on floating point numbers by Bartek Szopka
// http://t.co/Yiu5HfRoER
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment