What does '!!~' do in Javascript? [duplicate] - javascript

This question already has answers here:
How does !!~ (not not tilde/bang bang tilde) alter the result of a 'contains/included' Array method call?
(13 answers)
Closed 4 years ago.
I saw following piece of code on github.
/**
* Filters an array of objects with multiple criteria.
*
* #param {Array} array: the array to filter
* #param {Object} filters: an object with the filter criteria as the property names
* #return {Array}
*/
function multiFilter(array, filters) {
const filterKeys = Object.keys(filters);
// filters all elements passing the criteria
return array.filter((item) => {
// dynamically validate all filter criteria
return filterKeys.every(key => !!~filters[key].indexOf(item[key]));
});
}
I don't understand, what does !!~ do here?
PS: I know C and C++ languages and but I'm newbie with Javascript. I know about that operators but I don't understand, Why does use double negation(!!) with bitwise not(~) operator?

indexOf will return the index 0-x if the element is found, -1 otherwise.
~ will change all the bits in the number, turning -1 to 0 (the binary represantation of -1 is 1111 1111 ...).
0 is a falsy value, all other numbers are truthy.
!! will convert a falsy value to false and a truthy value to true. It wouldn't be needed here, because every doesn't care whether it recieves a truthy value or true.
As others have mentioned, nowadays you could use includes. However, includes is newer to the JavaScript ecosystem than indexOf, so this solution would work in IE, the solution with include would not. You could still use includes in IE either by providing a polyfill or by transpiling your code.

The tilde turns the resulting indexOf expression truthy if the item is found, and falsey if the item is not found. The !! then converts the result to a boolean from a number. (which is not useful at all, since every only cares about whether the result is truthy or falsey)
It's terribly unclear. It would be much better to use this instead:
return array.filter((item) => {
// dynamically validate all filter criteria
return filterKeys.every(key => filters[key].includes(item[key]));
});

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = ~fruits.indexOf("Banana");
var b = !a;
var c = !!a;
console.log('a:',a);
console.log('b:',b);
console.log('c:',c);
It can be break into steps as above to trying to understand what's going on. Bitwise operator: ~ is a common way to replace the ugly 0/-1 comparison when using indexOf method. A double negation using !! will gives us a Boolean to tell whether it's found or not found

!!~ means bitwise not ~ followed by double negation !!.
Bitwise not operates by reversing all the bits in the operand.

Related

How to convert BigInt to Number in JavaScript?

I found myself in the situation where I wanted to convert a BigInt value to a Number value. Knowing that my value is a safe integer, how can I convert it?
Turns out it's as easy as passing it to the Number constructor:
const myBigInt = BigInt(10); // `10n` also works
const myNumber = Number(myBigInt);
Of course, you should bear in mind that your BigInt value must be within [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER] for the conversion to work properly, as stated in the question.
You can use parseInt or Number
const large = BigInt(309);
const b = parseInt(large);
console.log(b);
const n = Number(large);
console.log(n);
Edit: see the discussion in the comments below as to why this answer is not correct. I am leaving the answer up regardless for disambiguation.
You should use either of the static methods:
BigInt.asIntN() - Clamps a BigInt value to a signed integer value, and returns that value.
BigInt.asUintN() - Clamps a BigInt value to an unsigned integer value, and returns that value.
as documented here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#static_methods

Is it safe to use JavaScript's Math.max on an array of strings?

This seems to work, on an array of strings that look like numbers (they're numbers from a CSV file read in with csv-parse, which seems to convert everything into strings):
var a = ['123.1', '1234.0', '97.43', '5678'];
Math.max.apply(Math, a);
Returns 5678.
Does Math.max convert strings to numbers automatically?
Or should I do a + conversion myself first to be extra safe?
Does Math.max convert strings to numbers automatically?
Quoting the ECMA Script 5.1 Specification for Math.max,
Given zero or more arguments, calls ToNumber on each of the arguments and returns the largest of the resulting values.
So, internally all the values are tried to convert to a number before finding the max value and you don't have to explicitly convert the strings to numbers.
But watch out for the NaN results if the string is not a valid number. For example, if the array had one invalid string like this
var a = ['123.1', '1234.0', '97.43', '5678', 'thefourtheye'];
console.log(Math.max.apply(Math, a));
// NaN
You'll get a NaN if any of the strings aren't numbers, but otherwise it should work fine. I'd add the + just to be safe.
Consider this situation:
<script>
var a=['123.1', '1234.0', '97.43', '5678','0 11111111'];
console.log(Math.max.apply(Math, a));
</script>
You need to cast elements from array to be extra safe..
if you intend to check for the max element in an array of strings using Math.max() method. you can compare the length of reach element
question: var a = ['123.1', '1234.0', '97.43', '5678'];
const checkLength = Math.max.apply(null, a.map(element => element.length));
or using spread operator for shorter form
const checkLength = Math.max(...a.map(element => element.length));
then filter to get all the elements
a.filter(elem => elem.length === checkLength)

what's the " !~" mean in javascript [duplicate]

This question already has answers here:
What does a tilde do when it precedes an expression?
(5 answers)
Closed 8 years ago.
(function () {
var names = [];
return function (name) {
addName(name);
}
function addName(name) {
if (!~names.indexOf(name))//
names.push(name);
console.log(names);// ["linkFly"]
}
}())('linkFly');
sometimes i have seen this logical,what is it mean ?
thanks ~
tl;dr
indexOf returns -1 when an element cannot be found in an array. Therefore, the if statement is checking if name could not be found in names. !~-1 ==> true
Longer version:
The tilde (~) operator (bitwise NOT) yields the inverted value (a.k.a. one’s complement) of a. [Source] For example, ~-1 === 0. Note that 0 == false and !0 === true. indexOf returns -1 when an element cannot be found in an array. Therefore, we can use !~-1 === true to find out if indexOf could not find name in names (i.e. returned -1).
My opinion:
As you can see, using these obfuscated or "clever" techniques without comments can really confuse the reader. If you do love these techniques, please document what your line(s) of code are doing for the sake of the readers!
! (Logical NOT)
Returns false if its single operand can be converted to true; otherwise, returns true.
For all integer operands except -1, the net operand after applying the ~ operator for the ! operator would be truthy in nature resulting in FALSE.
-1 is special because ~(-1) gives 0 which is falsy in JavaScript. Adding the ! operator gives us the only TRUE.

In which cases should `==` be used over `localeCompare` and viceversa, in Javascript?

What are the pros and cons of each of them when compared to each other?
In which cases should == be used over localeCompare and viceversa, in Javascript?
They are not at all the same!
Non-strict comparison compares strings to see if they are the same (only included strings as that's what localeCompare works on, types are irrelevant).
"test" == "test" // true
localCompare is a lot more than that, it returns a number indicating whether a reference string comes before or after or is the same as the given string in sort order, and in the specified language.
'a'.localeCompare('c') // returns a negative value, i.e. -1 etc, a comes before c
'a'.localeCompare('a') // returns 0, they are the same
'c'.localeCompare('a') // returns a positinve value, i.e. 1 etc, c comes after a
note that the sort order used is entirely implementation dependent, but in most browsers it will be alphabetical
or language specific
'ä'.localeCompare('z', 'sv')); // a positive value: in Swedish, ä sorts after z
As it return a negative integer, zero or a positive integer, it's useful in functions such as sort() which expects the return of the sorting callback to be just that, a negative integer, zero or a positive integer.
MDN
localeCompare is not the same as ==. When you compare two variables using ==, you check whether or not the variables have the same content. This will return a boolean (true/false). However, localeCompare does not return a boolean but an int instead.
You will receive a 0 when the two variables are the same, but you will however receive either 1 or -1 if your variables are not the same. The value is based on whether the first variable comes before or after the second variable in sort order.
So I myself would use == when I'm purely validating if two variables are the same, but localeCompare can become handy when you want to see what variable comes first in sort order, however it can be used to compare two variables to see if they are the same.
string a = "hello";
string b = "world";
a == b // returns false
a.localeCompare(b); // returns -1
To answer your question slightly, these are the characteristics / pro's and cons of using either of the examples given:
Using ==
Returns a boolean instead of a string/integer/...
Easier to read by most people
Using localeCompare
Returns an integer (-1, 0 or +1)
Can be used to sort variables
localeCompare doesn't just check for equality in value. It also compares the values when they're different, and returns a 1 / -1 depending on which value is higher. It's return value is in no way similar to a equality check.
localeCompare can be used for sorting strings, as the return value is different from == when the 2 values aren't the same, == can only be used for determining equality (in value, not type).
For example:
"2".localeCompare(2) // 0
"2".localeCompare(1) // 1
"2".localeCompare(3) // -1
"2" == 2 // true
"2" == 1 // false
"2" == 3 // false
"b".localeCompare("b") // 0
"b".localeCompare("a") // 1
"b".localeCompare("c") // -1
"b" == "b" // true
"b" == "a" // false
"b" == "c" // false
The return value from localeCompare happens to be exactly what Array.prototype.sort() expects to be returned from it's handler.
localeCompare is very useful to implement a sorting (ascending or descending) function:
myLabelsArray.sort(function(a, b){
return a.label.localeCompare(b.label);
});
Indeed, localeCompare returns -1, 0 (if equals) or 1 (based on locale language rules), allowing to get a sorting.
It would take more lines to implement it with == + <, explicitly returning integers.

How does the following piece of expression evaluates to "10" [duplicate]

This question already has answers here:
Why does ++[[]][+[]]+[+[]] return the string "10"?
(10 answers)
Closed 6 years ago.
I have recently seen an expression from a source, which looks something like below -
++[[]][+[]]+[+[]]
Entering this into the Chrome (Windows 7, Version 27.0.1453.94 m) console shows a result of "10".
Can someone explain what's happening here?
JSFiddle.
JavaScript is fairly flexible about converting between data types. The first thing to notice is that +[] evaluates to 0.* That lets us rewrite the expression as:
++[[]][0] + [0]
The next thing to notice is that ++[[]][0] is the preincrement operator applied to the first element of [[]]. Normally you can't apply ++ to an array, but JavaScript kindly converts the first element to 0, so the result is that ++[[]][0] evaluates to 1 (the first element of [[]] having now been incremented). It is kind of like this:
var a = [[]];
var b = ++a[0];
// now a will be [1] and b will be 1
That leaves us with:
1 + [0]
JavaScript now converts the int and the array to strings (since [0] is not a numeric value) and concatenates them together. Done!
* My understanding of how +[] becomes 0 is that it is a two-step process: first, [] is converted to a string primitive, which is the empty string. The empty string then converts to a number, which is zero. Via the same route, [1] evaluates to '1' and then to 1, [2] evaluates to 2, etc. However, [1, 2] evaluates to '1,2' which evaluates to NaN. (The last because the decimal point separator is ., not ,. I don't know what would happen if my locale were different.)
This expression stringifies valid Javascript constructs that yelds NaN, numbers, boolean undefined etc.
e.g.
+[] -> 0 //The unary plus operator is applied to the result of toString applied to an empty array (which is an empty string)
!+[] -> true
You can have a look also at this question,
and at the no alnum cheat sheets.
+[] is a number conversion from array to number which is 0.
and +[0] is also 0.
So the final result can be deduced to (++0) + [0] which is 1+[0].
And for a number adding an array. They are converted to string so the result is actually '10'.
You can log typeof(++[[]][+[]]+[+[]]) to verify.

Categories

Resources