Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does a tilde do when it precedes an expression?

var attr = ~'input,textarea'.indexOf( target.tagName.toLowerCase() )
           ? 'value'
           : 'innerHTML'

I saw it in an answer, and I've never seen it before.

What does it mean?

like image 699
wwaawaw Avatar asked Sep 06 '12 12:09

wwaawaw


People also ask

What is the purpose of a tilde?

The tilde (~) is used in phonetics to show intention of pronunciation, and it placed above a letter, below a letter, or superimposed onto the middle of a letter. Here is a summary: When placed above the letter, the tilde indicates nasalization.

What does tilde mean in assembly?

Last updated: September 8, 2017. In JavaScript, the tilde ~ Bitwise NOT operator is commonly used right before an indexOf() to do a boolean check (truthy/falsy) on a string. On its own, indexOf() returns the index number of a String object passed in.

What does a tilde symbol mean?

As a mathematical symbol, the tilde means "approximately" and in logic it means "not." The tilde is one of the 128 alphanumeric and special characters in ASCII, the most common standard for electronic text exchange. The tilde happens to be ASCII character 126. This was last updated in January 2015.

What does the tilde operator mean?

In mathematics, the tilde operator (Unicode U+223C), sometimes called "twiddle", is often used to denote an equivalence relation between two objects. Thus "x ~ y" means "x is equivalent to y". It is a weaker statement than stating that x equals y.


5 Answers

~ is a bitwise operator that flips all bits in its operand.

For example, if your number was 1, its binary representation of the IEEE 754 float (how JavaScript treats numbers) would be...

0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

So ~ converts its operand to a 32 bit integer (bitwise operators in JavaScript do that)...

0000 0000 0000 0000 0000 0000 0000 0001

If it were a negative number, it'd be stored in 2's complement: invert all bits and add 1.

...and then flips all its bits...

1111 1111 1111 1111 1111 1111 1111 1110

So what is the use of it, then? When might one ever use it?

It has a quite a few uses. If you're writing low level stuff, it's handy. If you profiled your application and found a bottleneck, it could be made more performant by using bitwise tricks (as one possible tool in a much bigger bag).

It's also a (generally) unclear trick to turn indexOf()'s found return value into truthy (while making not found as falsy) and people often use it for its side effect of truncating numbers to 32 bits (and dropping its decimal place by doubling it, effectively the same as Math.floor() for positive numbers).

I say unclear because it's not immediately obvious what it is being used for. Generally, you want your code to communicate clearly to other people reading it. While using ~ may look cool, it's generally too clever for its own good. :)

It's also less relevant now that JavaScript has Array.prototype.includes() and String.prototype.includes(). These return a boolean value. If your target platform(s) support it, you should prefer this for testing for the existence of a value in a string or array.

like image 181
alex Avatar answered Sep 30 '22 17:09

alex


Using it before an indexOf() expression effectively gives you a truthy/falsy result instead of the numeric index that's directly returned.

If the return value is -1, then ~-1 is 0 because -1 is a string of all 1 bits. Any value greater than or equal to zero will give a non-zero result. Thus,

if (~someString.indexOf(something)) {
}

will cause the if code to run when "something" is in "someString". If you try to use .indexOf() as a boolean directly, then that won't work because sometimes it returns zero (when "something" is at the beginning of the string).

Of course, this works too:

if (someString.indexOf(something) >= 0) {
}

and it's considerably less mysterious.

Sometimes you'll also see this:

var i = ~~something;

Using the ~ operator twice like that is a quick way to convert a string to a 32-bit integer. The first ~ does the conversion, and the second ~ flips the bits back. Of course if the operator is applied to something that's cannot be converted to a number, you get NaN as a result. (edit — actually it's the second ~ that is applied first, but you get the idea.)

like image 24
Pointy Avatar answered Oct 01 '22 17:10

Pointy


The ~ is Bitwise NOT Operator, ~x is roughly the same as -(x+1). It is easier to understand, sort of. So:

~2;    // -(2+1) ==> -3

Consider -(x+1). -1 can perform that operation to produce a 0.

In other words, ~ used with a range of number values will produce a falsy (coerce to false from 0) value only for the -1 input value, otherwise, any other truthy value.

As we know, -1 is commonly called a sentinel value. It is used for many functions that return >= 0 values for success and -1 for failure in C language. Which the same rule of return value of indexOf() in JavaScript.

It is common to check of presence/absence of a substring in another string in this way

var a = "Hello Baby";

if (a.indexOf("Ba") >= 0) {
    // found it
}
if (a.indexOf("Ba") != -1) { 
    // found it
}

if (a.indexOf("aB") < 0) { 
    // not found
}
if (a.indexOf( "aB" ) == -1) { 
    // not found
}

However, it would be more easily to do it through ~ as below

var a = "Hello Baby";

~a.indexOf("Ba");         // -7   -> truthy
if (~a.indexOf("Ba")) {   // true
    // found it
}

~a.indexOf("aB");         // 0    -> falsy
!~a.indexOf("aB");        // true
if (!~a.indexOf( "aB" )) {  // true
    // not found
}

You Don't Know JS: Types & Grammar by Kyle Simpson

like image 33
zangw Avatar answered Oct 02 '22 17:10

zangw


~indexOf(item) comes up quite often, and the answers here are great, but maybe some people just need to know how to use it and "skip" the theory:

   if (~list.indexOf(item)) {
     // item in list
   } else {
     // item *not* in list
   }
like image 37
Jorge Bucaran Avatar answered Oct 02 '22 17:10

Jorge Bucaran


For those considering using the tilde trick to create a truthy value from an indexOf result, it is more explicit and has less magic to instead use the includes method on String.

'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false

Note that this is a new standard method as of ES 2015 so it won't work on older browsers. In cases where that matters, consider using the String.prototype.includes polyfill.

This feature is also available for arrays using the same syntax:

['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false

Here is the Array.prototype.includes polyfill if you need older browser support.

like image 45
Dana Woodman Avatar answered Sep 29 '22 17:09

Dana Woodman