Useful JS Tips

#15 - Even simpler way of using indexOf as a contains clause

2016-01-15 by @jhogoforbroke

JavaScript by default does not have a contains method. And for checking existence of a substring in a string or an item in an array you may do this:

var someText = 'javascript rules';
if (someText.indexOf('javascript') !== -1) {
}

// or
if (someText.indexOf('javascript') >= 0) {
}

But let’s look at these Expressjs code snippets.

examples/mvc/lib/boot.js

for (var key in obj) {
  // "reserved" exports
  if (~['name', 'prefix', 'engine', 'before'].indexOf(key)) continue;

lib/utils.js

exports.normalizeType = function(type){
  return ~type.indexOf('/')
    ? acceptParams(type)
    : { value: mime.lookup(type), params: {} };
};

examples/web-service/index.js

// key is invalid
if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));

The gotcha is the bitwise operator ~, “Bitwise operators perform their operations on binary representations, but they return standard JavaScript numerical values.”

It transforms -1 into 0, and 0 evaluates to false in JavaScript:

var someText = 'text';
!!~someText.indexOf('tex'); // someText contains "tex" - true
!~someText.indexOf('tex'); // someText NOT contains "tex" - false
~someText.indexOf('asd'); // someText doesn't contain "asd" - false
~someText.indexOf('ext'); // someText contains "ext" - true

String.prototype.includes()

ES6 introduced the includes() method and you can use it to determine whether or not a string includes another string:

'something'.includes('thing'); // true

With ECMAScript 2016 (ES7) it is even possible to use these techniques with Arrays:

!!~[1, 2, 3].indexOf(1); // true
[1, 2, 3].includes(1); // true

Unfortunately, it is only supported in Chrome, Firefox, Safari 9 or above and Edge; not IE11 or lower. It’s better used in controlled environments.

<<返回目录