If you read the comments at the jQuery inArray page here, there's an interesting declaration:
!!~jQuery.inArray(elm, arr)
Now, I believe a double-exclamation point will convert the result to type boolean, with the value of true. What I don't understand is what is the use of the tilde (~) operator in all of this?
var arr = ["one", "two", "three"];
if (jQuery.inArray("one", arr) > -1) { alert("Found"); }
Refactoring the if statement:
if (!!~jQuery.inArray("one", arr)) { alert("Found"); }
Breakdown:
jQuery.inArray("one", arr) // 0
~jQuery.inArray("one", arr) // -1 (why?)
!~jQuery.inArray("one", arr) // false
!!~jQuery.inArray("one", arr) // true
I also noticed that if I put the tilde in front, the result is -2.
~!!~jQuery.inArray("one", arr) // -2
I don't understand the purpose of the tilde here. Can someone please explain it or point me towards a resource?
There's a specfic reason you'll sometimes see ~ applied in front of $.inArray.
Basically,
~$.inArray("foo", bar)
is a shorter way to do
$.inArray("foo", bar) !== -1
$.inArray returns the index of the item in the array if the first argument is found, and it returns -1 if its not found. This means that if you're looking for a boolean of "is this value in the array?", you can't do a boolean comparison, since -1 is a truthy value, and when $.inArray returns 0 (a falsy value), it means its actually found in the first element of the array.
Applying the ~ bitwise operator causes -1 to become 0, and causes 0 to become `-1. Thus, not finding the value in the array and applying the bitwise NOT results in a falsy value (0), and all other values will return non-0 numbers, and will represent a truthy result.
if (~$.inArray("foo", ["foo",2,3])) {
// Will run
}
And it'll work as intended.
!!~expr evaluates to false when expr is -1 otherwise true.
It is same as expr != -1, only broken*
It works because JavaScript bitwise operations convert the operands to 32-bit signed integers in two's complement format. Thus !!~-1 is evaluated as follows:
-1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's complement representation of -1
~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits)
!0 = true // ! is logical not (true for falsy)
!true = false // duh
A value other than -1 will have at least one bit set to zero; inverting it will create a truthy value; applying ! operator twice to a truthy value returns boolean true.
When used with .indexOf() and we only want to check if result is -1 or not:
!!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false
!!~"abc".indexOf("a") // indexOf() returns 0, the expression evaluates to true
!!~"abc".indexOf("b") // indexOf() returns 1, the expression evaluates to true
* !!~8589934591 evaluates to false so this abomination cannot be reliably used to test for -1.
The tilde operator isn't actually part of jQuery at all - it's a bitwise NOT operator in JavaScript itself.
See The Great Mystery of the Tilde(~).
You are getting strange numbers in your experiments because you are performing a bitwise logical operation on an integer (which, for all I know, may be stored as two's complement or something like that...)
Two's complement explains how to represent a number in binary. I think I was right.
~foo.indexOf(bar) is a common shorthand to represent foo.contains(bar) because the contains function doesn't exist.
Typically the cast to boolean is unnecessary due to JavaScript's concept of "falsy" values. In this case it's used to force the output of the function to be true or false.
jQuery.inArray() returns -1 for "not found", whose complement (~) is 0. Thus, ~jQuery.inArray() returns a falsy value (0) for "not found", and a truthy value (a negative integer) for "found". !! will then formalise the falsy/truthy into real boolean false/true. So, !!~jQuery.inArray() will give true for "found" and false for "not found".
The ~ for all 4 bytes int is equal to this formula -(N+1)
SO
~0 = -(0+1) // -1
~35 = -(35+1) // -36
~-35 = -(-35+1) //34
Tilde is bitwise NOT - it inverts each bit of the value. As a general rule of thumb, if you use ~ on a number, its sign will be inverted, then 1 will be subtracted.
Thus, when you do ~0, you get -1 (0 inverted is -0, subtract 1 is -1).
It's essentially an elaborate, super-micro-optimised way of getting a value that's always Boolean.
The ~ operator is the bitwise complement operator. The integer result from inArray() is either -1, when the element is not found, or some non-negative integer. The bitwise complement of -1 (represented in binary as all 1 bits) is zero. The bitwise-complement of any non-negative integer is always non-zero.
Thus, !!~i will be true when integer "i" is a non-negative integer, and false when "i" is exactly -1.
Note that ~ always coerces its operand to integer; that is, it forces non-integer floating point values to integer, as well as non-numeric values.
You're right: This code will return false when the indexOf call returns -1; otherwise true.
As you say, it would be much more sensible to use something like
return this.modifiedPaths.indexOf(path) !== -1;
The ~ operator is the bitwise NOT operator. What this means is that it takes a number in binary form and turns all zeroes into ones and ones into zeroes.
For instance, the number 0 in binary is 0000000, while -1 is 11111111. Likewise, 1 is 00000001 in binary, while -2 is 11111110.
My guess is that it is there because it's a few characters shorter (which library authors are always after). It also uses operations that only take a few machine cycles when compiled into the native code (as opposed to the comparison to a number.)
I agree with another answer that it's an overkill but perhaps might make sense in a tight loop (requires performance gain estimation, though, otherwise may turn out to be premature optimization.)
I assume, since it is a bitwise operation, it is the fastest (computationally cheap) way to check whether path appears in modifiedPaths.
As (~(-1)) === 0, so:
!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false
Related
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?
~ 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.
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.)
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
~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
}
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.
~(function () {}).toString(); is absolutely valid JavaScript syntax and I saw that it returns -1.
I know that ~ is not operator. For instance ~5=~0101 which means 1010 in base 2 and 10 in decimal.
console.log(~(function () {}).toString());
But what is the explanation in this situation ?
Maybe ~NaN returns -1.
As per spec
Let oldValue be ToInt32(GetValue(expr)).
Number((function () {}).toString();) -> Number("function () {}") -> NaN
Again as per spec
If number is NaN, +0, −0, +∞, or −∞, return +0.
so ~NaN amounts to ~0 which is -1
Taken from this blog: The Great Mystery of the Tilde(~):
The tilde is an operator that does something that you’d normally think wouldn’t have any purpose. It is a unary operator that takes the expression to its right performs this small algorithm on it (where N is the expression to the right of the tilde): -(N+1). See below for some samples.
console.log(~-2); // 1
console.log(~-1); // 0
console.log(~0); // -1
console.log(~1); // -2
console.log(~2); // -3
As far as I know, in math both Infinity and NaN are vague values.
as all of us know:
console.log(NaN == NaN); //-> false
while
console.log(Infinity==Infinity); //-> true
I'm wondering why the result of the second code is true. I'm expecting that the result of the second one, should be false, but it's not.
Could you please help me out.
I'd really appreciate it. Thanks.
This is why:
NaN compares unequal (via ==, !=, ===, and !==) to any other value -- including to another NaN value. Use Number.isNaN() or isNaN() to most clearly determine whether a value is NaN. Or perform a self-comparison: NaN, and only NaN, will compare unequal to itself.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN
The initial value of Infinity is Number.POSITIVE_INFINITY. The value Infinity (positive infinity) is greater than any other number. This value behaves mathematically like infinity; for example, any positive number multiplied by Infinity is Infinity, and anything divided by Infinity is 0.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity
What you also might be interested in is using the isFinite method of Number:
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Read up on Number.isFinite(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite
In addition to the other answers: Because the spec says so.
NaN is the only value in JavaScript that is not equal to itself:
A reliable way for ECMAScript code to test if a value X is a NaN is an expression of the form X !== X. The result will be true if and only if X is a NaN.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.4
Because processors interpret it that way. Most math in JS follows the IEEE-754 specification for floating math arithmetic, which processors implement in pretty specific ways. That includes NaN !== NaN and Infinity === Infinity, among other things.
infinity is treated as a numeric value, so infinity==infinity represents one numeric value equaling another. While in common mathematics the infinity can not be compared against infinity, in javascript it can!
NaN on the other hand, is a type of undefined variable, not a number. So comparisons between NaN are not logically comparable. The proper way to compare against NaN is with the function isNaN.
Example:
isNaN(NaN) // returns true
I'm reading this javascript function:
if (~['bacon', 'burger'].indexOf(type)) {
this.res.writeHead(200, { 'Content-Type': 'text/plain' });
this.res.end('Serving ' + type + ' sandwich!\n');
}
But I'm not sure what means ~ some one know when I use it or what meaning?
~ is the bitwise NOT operator. It toggles every bit of a number.
0 becomes -1.
-1 becomes 0.
No other numbers become zero.
That means that
if (~['bacon', 'burger'].indexOf(type)) {
is a confusing way of writing
if (['bacon', 'burger'].indexOf(type) == -1) {
indexOf returns -1 when it doesn't find the string.
~ is a Bitwise NOT operator...
Read more
In this instance, the ~ allows that code to turn the return value of .indexOf() — which is a number indicating the position of the searched-for value in the array — into a boolean. In other words, it takes the "where is the value" result and turns it into a "is the value in the list" result.
How? Well, .indexOf() returns -1 when the value is not found, and a number greater than or equal to zero if it is. The ~ operator converts its numeric argument to a 32-bit integer and then inverts every bit. That process happens to turn -1 to 0, and any positive integer to some negative non-zero value, and 0 to -1. When such results are subsequently examined as boolean values, the original -1 will be false (because 0 is "falsy") while the integers greater than or equal to zero will be true (because they're all converted to some non-zero value).
Bitwise NOT (~ a) Inverts the bits of its operand.
EXAMPLE
9 (base 10) = 00000000000000000000000000001001 (base 2)
--------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base
10)
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
A questions that stumped me on this JavaScript test was that ~null evaluates to -1.
Why does ~null evaluate to -1?
That's because ~ is a numeric operator, so it casts null to 0 first:
> ~0
-1
It would be equivalent to this expression:
~(+null)
Likewise:
> ~[]
-1
> ~{}
-1
First of all, ~ is a bitwise NOT operator. That means it flips all the bits in the number representation. 0010 1010 becomes 1101 0101.
As a consequence of computers using 2's complement for storing numbers, this equality holds:
~number == -number - 1
As can be shown from my previous example:
0010 1010 (this represents number 42)
1101 0101 (this represents number -43)
Now, because ~ is an operator that operates on numbers, its argument gets cast to a number first. Since null gets cast to a 0, you get -1 as a result (according the above equation).