Saw this in my newsletter. Tested on Chrome and Firefox. I still can't figured it out.
[]+(-~{}-~{}-~{}-~{})+(-~{}-~{}); //=> "42"
Evaluating:
~{}
is evaluated using the internal function:
~ToInt32({})
which gives -1.
Ref ECMA spec - http://www.ecma-international.org/ecma-262/5.1/#sec-9.5
and this explanation - http://jibbering.com/faq/notes/type-conversion/#tcToInt32
Therefore, in this case
(-~{}-~{}) == 2
(-~{}-~{}-~{}-~{}) == 4
As you have []+ in the start of expression, javascript use plus operands like string. So you have "" + "4" + "2" = "42"
The ~ operator is a Bitwise NOT operator. It returns the "1's complement" of a number. Because of that {} is converted into a number, resulting in NaN. The same would happen with +{} == NaN. The bitwise not of ~NaN == -1. So:
(-~{}-~{}-~{}-~{}) == 4 & (-~{}-~{}) == 2
The DefaultValue for an empty array is an empty string. For example []==[]+[] && []+[]==''
From that, the full parsing is:
[]+ /*converted to ''+*/ (-~{}-~{}-~{}-~{}) /*Equals numeric 4, but concatenated as a string to become '4'*/ + (-~{}-~{}) /*Equals numeric 2, but concatenated as a string to become '2'*/ and the end result is actually '42'.
You can validate this via typeof([]+(-~{}-~{}-~{}-~{})+(-~{}-~{})) === 'string'
Related
I store some parameters client-side in HTML and then need to compare them as integers. Unfortunately I have come across a serious bug that I cannot explain. The bug seems to be that my JS reads parameters as strings rather than integers, causing my integer comparisons to fail.
I have generated a small example of the error, which I also can't explain. The following returns 'true' when run:
console.log("2" > "10")
Parse the string into an integer using parseInt:
javascript:alert(parseInt("2", 10)>parseInt("10", 10))
Checking that strings are integers is separate to comparing if one is greater or lesser than another. You should always compare number with number and string with string as the algorithm for dealing with mixed types not easy to remember.
'00100' < '1' // true
as they are both strings so only the first zero of '00100' is compared to '1' and because it's charCode is lower, it evaluates as lower.
However:
'00100' < 1 // false
as the RHS is a number, the LHS is converted to number before the comparision.
A simple integer check is:
function isInt(n) {
return /^[+-]?\d+$/.test(n);
}
It doesn't matter if n is a number or integer, it will be converted to a string before the test.
If you really care about performance, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
return function(n) {
return re.test(n);
}
}());
Noting that numbers like 1.0 will return false. If you want to count such numbers as integers too, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
var re2 = /\.0+$/;
return function(n) {
return re.test((''+ n).replace(re2,''));
}
}());
Once that test is passed, converting to number for comparison can use a number of methods. I don't like parseInt() because it will truncate floats to make them look like ints, so all the following will be "equal":
parseInt(2.9) == parseInt('002',10) == parseInt('2wewe')
and so on.
Once numbers are tested as integers, you can use the unary + operator to convert them to numbers in the comparision:
if (isInt(a) && isInt(b)) {
if (+a < +b) {
// a and b are integers and a is less than b
}
}
Other methods are:
Number(a); // liked by some because it's clear what is happening
a * 1 // Not really obvious but it works, I don't like it
Comparing Numbers to String Equivalents Without Using parseInt
console.log(Number('2') > Number('10'));
console.log( ('2'/1) > ('10'/1) );
var item = { id: 998 }, id = '998';
var isEqual = (item.id.toString() === id.toString());
isEqual;
use parseInt and compare like below:
javascript:alert(parseInt("2")>parseInt("10"))
Always remember when we compare two strings.
the comparison happens on chacracter basis.
so '2' > '12' is true because the comparison will happen as
'2' > '1' and in alphabetical way '2' is always greater than '1' as unicode.
SO it will comeout true.
I hope this helps.
You can use Number() function also since it converts the object argument to a number that represents the object's value.
Eg: javascript:alert( Number("2") > Number("10"))
+ operator will coerce the string to a number.
console.log( +"2" > +"10" )
The answer is simple. Just divide string by 1.
Examples:
"2" > "10" - true
but
"2"/1 > "10"/1 - false
Also you can check if string value really is number:
!isNaN("1"/1) - true (number)
!isNaN("1a"/1) - false (string)
!isNaN("01"/1) - true (number)
!isNaN(" 1"/1) - true (number)
!isNaN(" 1abc"/1) - false (string)
But
!isNaN(""/1) - true (but string)
Solution
number !== "" && !isNaN(number/1)
The alert() wants to display a string, so it will interpret "2">"10" as a string.
Use the following:
var greater = parseInt("2") > parseInt("10");
alert("Is greater than? " + greater);
var less = parseInt("2") < parseInt("10");
alert("Is less than? " + less);
I know Lodash often adds some extra checks or niceties to functions that already exist in JavaScript but it's not clear what _.toNumber specifically does that I wouldn't get with parseInt.
I'd prefer to use Lodash only when it provides benefits that aren't there with existing JavaScript functions but I can't see any in this case.
I think it is much better to simply look at the _.toNumber source and that would practically answer your question:
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
As you can see it does a bunch of other things in comparison to parseInt. To be more specific:
console.log(_.toNumber(1), parseInt(1)) // same
console.log(_.toNumber('1'), parseInt('1')) // same
console.log(_.toNumber('b'), parseInt('b')) // same
console.log(_.toNumber({}), parseInt({})) // same
console.log(_.toNumber(' 1 '), parseInt(' 1 ')) // same
console.log(_.toNumber([1]), parseInt([1])) // same
console.log(_.toNumber(' 1a1 '), parseInt(' 1a1 ')) // NaN 1
console.log(_.toNumber([1,2]), parseInt([1,2])) // NaN 1
console.log(_.toNumber(false), parseInt(false)) // 0 NaN
console.log(_.toNumber(!0), parseInt(!0)) // 1 NaN
console.log(_.toNumber(!!0), parseInt(!!0)) // 0 NaN
console.log(_.toNumber(5e-324), parseInt(5e-324)) // 5e-324 5
console.log(_.toNumber(5.5), parseInt(5.5)) // 5.5 5
console.log(_.toNumber(null), parseInt(null)) // 0 NaN
console.log(_.toNumber(Infinity),parseInt(Infinity)) // Infinity NaN
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
So to summarize _.isNumber gives you more expected / consistent and I would argue safer results when it comes to parsing input with arrays, decimals, falsy values and strings. It would check the entire input vs parseInt which only cares about the first valid value as you can see from the examples above. It also handles better the negate operator (!) etc.
So overall it does have its uses vs parseInt
Note: What is a gotcha here is that both _.toNumber and parseInt return NaN for undefined which considering how _.toNumber deals with the rest of the falsy values one would expect to return 0 vs NaN:
console.log(_.toNumber(undefined), parseInt(undefined)) // NaN NaN
_.toNumber converts a given input to a number if such a conversion is possible, otherwise returns NaN. The parseInt and parseFloat methods also work in same manner (the former will only return integers though), however, they are much more lax in their parsing rules. _.toNumber is significantly more restrictive.
For eg, with same input '5.2a', parseInt would return 5, parseFloat would return 5.2, and _.toNumber would return NaN. The former two ignore everything after the first unrecognised character and return the number formed by all parsed characters till that point. The last one however returns NaN if an unrecognised character is encountered.
_.toNumber is comparable and functionally same to Number function.
The value of the field with the id 'post_url' is http://www.example.com/. Shouldn't JavaScript return true for anything greater than -1?
alert('1a = '+id_('post_url').value.indexOf('http:'));// 0
alert('1b = '+id_('post_url').value.indexOf('http:') > -1);// false
alert('2a = '+id_('post_url').value.indexOf('www.'));// 7
alert('2b = '+id_('post_url').value.indexOf('www.') > -1);// false
You're comparing a string and a number. You're concatenating the result of indexOf (which I assume is -1) to a string before you do your > comparison. This is equivalent to NaN > -1.
"1b-1" > -1 // => false
Check Operator Precedence
The addition/string concatenation has greater precedence than relational comparison.
Your code needs some brackets/grouping operator to cure that:
alert( '1b = ' + ( id_('post_url').value.indexOf('http:')>-1 ) ); // 1b = true
You are attempting to evaluate a string concatenation as a number, which is returning false.
'2b'+id_('post_url').value.indexOf('www.')>-1
...using order of operations, will add the string, 2B to the index returned by, id_('post_url').value.indexOf('www.')
Thus, casting the entire thing as a string, and evaluating whether the string is greater than -1.
Here's how you need to write your alert.
alert(id_('post_url').value.indexOf('www.')>-1);
That should alert 'true'.
'2b'+id_('post_url').value.indexOf('www.')
You are adding 2b to index of, so it won't remain an integer but will have value as string of 2b+ whatever index you have. So that is the reason for what you are observing.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Javascript === vs == : Does it matter which “equal” operator I use?
When would JavaScript == make more sense than ===?
What is the difference between below methods in comparing a string with undefined value.
var x;
if(x==undefined)
{
alert(x);
}
and
if(x===undefined)
{
alert(x);
}
Why should i prefer second method in this case.. Please let me know advantages..
== attempts to convert the values to the same type before testing if they're the same. "5" == 5
=== does not do this; it requires objects to be of the same type to be equal. "5" !== 5
In this case, the result is:
x == undefined will be true if x is undefined or null.
x === undefined will only be true if x is undefined.
You should prefer the first method if you'd like undefined and null to be treated equivalently. One common use of this is optional function arguments.
function greet(name, greeting) {
if (name == undefined) name = 'World';
if (greeting == undefined) greeting = 'Hello';
alert(greeting + ' ' + name);
}
greet(); // alerts "Hello World"
greet("Bob"); // alerts "Hello Bob"
greet(null, "Goodbye"); // alerts "Goodbye World"
suppose we have x=5,
== is equal to
x==8 is false
x==5 is true
=== is exactly equal to (value and type)
x===5 is true
x==="5" is false
Hope you understand this concept
=== checks for the same type as well. You'll understand with a few examples:
(1 == '1') //Returns true
Since == doesn't bother with types, that returns true. However, if you want strict type checking, you'd use === because that returns true only if the it's of the same type, and is the same value.
(1 === '1') //Returns false
(1 === 1) //Returns true
Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding
positions.
Two numbers are strictly equal when they are numerically equal (have the same number value). NaN is not equal to anything,
including NaN. Positive and negative zeros are equal to one another.
Two Boolean operands are strictly equal if both are true or both are false.
Two objects are strictly equal if they refer to the same Object.
Null and Undefined types are == (but not ===).
Reference
== is just comparing the two values, and if they are of different types, type conversion is done
=== compares the values and well as their types - so no type conversion will be done here.
Code-snippet 1:
if ( !x ) { /* do stuff */ }
Code-snippet 2:
if ( x == 0 ) { /* do stuff */ }
For what values of x do these two code-snippets differ?
I am asking because, although I read the chapter on == in the spec, I still find it hard to deal with situations like the above (where it is combined with ToBoolean coercion).
btw, I want to know this just for the sake of knowing it (I want to understand the language), so don't bother telling me about === or asking me what x is.
Update: I corrected the fist snippet. I meant !x.
[] == 0 is true; ![] is false
null == 0 is false; !null is true
NaN == 0 is false; !NaN is true
undefined == 0 is false; !undefined is true
!x will check whether x is "falsy".
x == 0 will check whether x is "equivalent to" 0.
Both of these terms are defined by the Javascript spec.
The following will give you true for the first and false for the second snippet:
NaN
null
undefined
And these will give you false for the first and true for the second snippet:
[]
"0" and any other string that converts to 0 using Number(x) such as "00", "000", "+0", and "-0" (which I will now call "noughty strings")
an array containing a single element that is 0, null, undefined or an empty or noughty string.
For everything else you'll get the same result for both snippets, although there may be one or two more cases I haven't thought of.
Here's an interesting one with regard to a non-empty String that has only space characters:
!!" "; // true
" " == true; // false
This is because when you do a == comparison, and one of the values being compared is a number or a boolean, an attempt is made to convert the other value to a number.
The reason you get the different result is that a string with only space characters converts to the number 0 (or falsey), while a string with only spaces converted to boolean via !! is seen as a non-empty string, and therefore true.
So:
var x = " ";
alert( !x ); // false
alert( x == 0 ); // true
EDIT:
Probably the key thing to remember is that when comparing a number or boolean to a non number type, == uses toNumber conversion if possible, while ! uses toBoolean conversion. They're not always the same.
It is easy to see the result of the toBoolean conversion using !!. As in:
alert( !![] ); // true
But you can't really see the result of the toNumber conversion when using ==.
You can, however, use the unary + to see the result of a toNumber conversion. As in:
alert( +[] ); // 0
I'm pretty sure that what happens in the case of an Array, is that it first gets a toString call. Therefore:
// ---------------------toString result-------toNumber result (from string)
alert( +[] ); // "" 0
alert( +[""] ); // "" 0
alert( +[" "] ); // " " 0
alert( +[0] ); // "0" 0
alert( +["0"] ); // "0" 0
alert( +["3"] ); // "3" 3
alert( +[3,4] ); // "3,4" NaN
Short answer: the two are almost always the same but not 100% the same.
An example would be (!'0') which is false whereas ('0' == 0) is true
Details:
From: http://www.joeyjavas.com/2007/08/04/javascript-true-false-checking-for-boolean-values/
Checking if a value is true or false is simple in JavaScript. All values evaluate to true, except for:
0
-0
null
undefined
NaN
empty string
false
Therefore, (!x) will be true for all of the above values of x and only those.
As for (x == 0), it will be true for any value of x which - when converted according to "==" conversion rules - is converted to 0 when compared to a number (for example, Boolean false value). Other examples that compare true to ==0 are objects which generate 0 from their valueOf() methods, or a string '0', or an empty Array ([])
The first test will succeed when x is non-zero, or evaluates to an object (as opposed to null or undefined), or is a non-empty string. So if x is 0 then the condition fails, but if it is "0" then it succeeds.
The second test will succeed when x is convertible to 0. This means it must not be null, undefined, or an object to pass this test. And it may be "0" or "".
In other words, these conditionals are not opposites. The value "0" will pass both tests, for example.
Code Snippet 1 will execute if x is "falsy" value. In Javascript, this means 0, -0, null, undefined, NaN, "", or false. Code Snippet 2, however, will only execute if x is zero. Unlike the first condition, this does not include other "falsy" values.
The difference between the two is that
if ( x ) { ... }
Tests whether x is "truthy"
Whereas
if ( x == 0 ) { ... }
Does type coercion between x and 0.
I presume you mean something like
if (x == 0) vs if (!x)
The main difference is type coercion of x to a number vs checking if x is falsy.
Clearly NaN itself will never equal 0 since its not a number. undefined will also coerce to NaN so that is not caught by == 0 I can't give a good explanation why null is not caught by 0 since Number(null) == 0
After some lookups, have to change my awnser.
There's no simple logic, implicit equality operations follows an algorithm.
http://interglacial.com/javascript_spec/a-11.html#a-11.9.3
I can't sum it up better then what the algoritm describes, it would just get more confusing.
So it's (!x) is equivalent to (typeof x === false) aka (not true)
And (x == 0) gets compared by algorithm.