JavaScript中默认是没有判断字符串是否被包含的contains
方法。当我们需要检测一个子字符串是否被另外一个字符串包含时,通常使用下面的方法:
1
2
3
4
5
6
7
8
9
var someText = 'javascript rules' ;
if (someText.indexOf('javascript' ) !== -1 ) {
}
if (someText.indexOf('javascript' ) >= 0 ) {
}
但是我们看一下Express 中的一些代码片段:
examples/mvc/lib/boot.js
1
2
3
for (var key in obj) {
if (~['name' , 'prefix' , 'engine' , 'before' ].indexOf(key)) continue ;
lib/utils.js
1
2
3
4
5
exports.normalizeType = function (type ){
return ~type .indexOf ('/')
? acceptParams(type )
: { value: mime.lookup(type ), params : {} };
};
examples/web-service/index.js
1
2
// key is invalid
if (!~apiKeys.indexOf(key )) return next(error (401 , 'invalid api key'))
其中的秘密就在于按位运算符 ~
“Bitwise operators perform their operations on binary representations, but they return standard JavaScript numerical values.” (按位运算符是将操作对象转换为二进制,在此基础上进行运算,但是运算的结果是标准的JavaScript数字类型 )
按位非运算会把-1转换为0, 而在JavaScript中,0可以被规范化为false
:
1
2
3
4
5
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中引入了新的方法includes()
,可以用来检测一个字符串是否包含另外一个字符串。
1
'something '.includes ('thing ')
在ECMAScript 2016 (ES7)中甚至可以将这项技术使用在数组中:
1
2
!!~[1 , 2 , 3 ].indexOf(1 );
[1 , 2 , 3 ].includes(1 );
不幸的是,这仅仅在Chrome, Firefox, Safari 9+ 和 Edge中被支持, IE11- 都不支持。最好使用在受控的环境中
译注: 上面是指浏览器原生的对ES6的支持,可以使用Babel等转换工具将ES6代码转换为ES5的。
补充: 为什么不能直接使用
1
2
3
if (someText.indexOf('javascript' )) {
}
判断呢,原因很简单,indexOf
的返回值可能是0,也就是字符串开始的位置,而0会被认为是false。
本文是js tips系列,翻译自 https://github.com/loverajoel/jstips