var PgrtiJr = {
"TWfbR": +((!+[] + !![] + !![] + !![] + []) + (!+[] + !![] + !![]))
};
PgrtiJr.TWfbR -= +((+!![] + []) + (+!![]));
console.log(parseInt(PgrtiJr.TWfbR, 10));
I have above mentioned js code. I executed this code on http://math.chapman.edu/~jipsen/js/. Can anybody explain me how it is equal to 32?
and can you recommend any python library that can evaluate this expression in python
tried execjs but no luck
You need to understand few important things about JavaScript's loose typing. Lets start with simpler things, specific to your question.
An empty array literal is considered truthy, but when you apply unary + operator, the array will be converted to a String and which will then be converted to a number. So, internally +[] evaluates to 0.
console.log(+[]);
// 0
Since [] is truthy, double negating it with logical not operator will give you true, which when used in an arithmetic expression, evaluate to 1, since 1 is loosely equal to true.
console.log(!![], 3 + !![]);
// true 4
Apart from all these, when we use an array literal with + operator, the array will be converted to a string and since one part of the expression is string, the other part of the expression will also be converted to string and string concatenation takes place. So the resulting object will be of type string.
console.log(typeof 1, typeof [], typeof (1 + []), 1 + []);
// number object string 1
With this basic understanding, lets analyze the first expression.
+((!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]))
Lets first take,
(!+[]+!![]+!![]+!![]+[])
Here, +[] evaluates to 0 and logical not makes it as true. Since we use it in an expression with a numeric operand, true is treated as 1. And as per our point 2 seen above, !![] evaluates to 1. So, the expression becomes 1 + 1 + 1 + 1 + [], which is actually 4 + []. And as per point 3, the number 4 will become string 4.
The same way, other part of the expression, (!+[]+!![]+!![]) becomes, 1 + 1 + 1 and which is actually 3. So when you do '4' + 3, you will get '43', which is a string. Now, we have a unary + operator which converts this string to a number. So, the result of evaluation of this expression becomes 43, which is a number.
The other part of the expression,
PgrtiJr.TWfbR -= +((+!![]+[])+(+!![]))
will be evaluated like this
+((1 + []) + 1)
and then
+('1' + 1)
and then
+'11'
which is then evaluated to 11. Since PgrtiJr.TWfbR is actually 43, 43 - 11 becomes 32. That is why you are getting 32 as the answer.
[] is an object that is equal to null.
!![] is a "boolean" that equals to true. (twice ! of null ( = false) )
!+[] is a "boolean" that equals to true.
and if we add a [] after this expressions, they will be converted to string.
so
(!+[]+!![]+!![]+!![]+[]) will be a string that equals 4
(!+[]+!![]+!![]) will be a string that equals 3
hence (!+[]+!![]+!![]+!![]+[]) + (!+[]+!![]+!![]) will be a string that equals 43
and +(!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]) will be a number that again equals 43
in the same way +((+!![]+[])+(+!![])) will equal to 11
so total of expression will equal to 43 - 11 = 32
Related
I am looking at the typeof a where var a = 2 + []. I expected the answer to be 2 of type number but I am getting '2' of type string. However, when I evaluate var b = 2 - [], I get the value to be 2 of type number. Can somebody assist me to understand this behavior.
const arr = [];
const a = 2 + arr;
console.log(a); // '2'
console.log(typeof a) // string
const b = 2 - arr;
console.log(b) // 2
console.log(typeof b); // number
//I expected the value a to be 2 of type
//number just as b
//If I toggle the boolean value of arr,
//both a and b evaluates to 2 of
//type number
+ with two operands is the "addition operator," which may do mathematical addition or string addition (concatenation) depending on its operands.
When any operand to + is an object, the JavaScript engine converts the object to a primitive. In your case, the array is an object. Converting an array to a primitive yields a string (as though you'd called their toString method, which basically does .join()). So then the + operator is dealing with a number and a string. When either operand is a string, + converts the other operand to string, and so you get "2" as the result. That is:
2 + [] becomes
2 + "" which becomes
"2" + "" which is
"2"
- with two operands is the "subtraction operator" and it's very different. It's only for math, it doesn't have any string meaning. That means it converts its arguments to numbers. Converting an array to number involves first converting it to a string, then converting the string to a number. [] becomes "" which converts to 0. So:
2 - [] becomes
2 - "" which becomes
2 - 0 which is
2
I was wondering what the = +_ operator means in JavaScript. It looks like it does assignments.
Example:
hexbin.radius = function(_) {
if (!arguments.length)
return r;
r = +_;
dx = r * 2 * Math.sin(Math.PI / 3);
dy = r * 1.5;
return hexbin;
};
r = +_;
+ tries to cast whatever _ is to a number.
_ is only a variable name (not an operator), it could be a, foo etc.
Example:
+"1"
cast "1" to pure number 1.
var _ = "1";
var r = +_;
r is now 1, not "1".
Moreover, according to the MDN page on Arithmetic Operators:
The unary plus operator precedes its operand and evaluates to its
operand but attempts to converts it into a number, if it isn't
already. [...] It can convert string representations of integers and
floats, as well as the non-string values true, false, and null.
Integers in both decimal and hexadecimal ("0x"-prefixed) formats are
supported. Negative numbers are supported (though not for hex). If it
cannot parse a particular value, it will evaluate to NaN.
It is also noted that
unary plus is the fastest and preferred way of converting something into a number
It is not an assignment operator.
_ is just a parameter passed to the function.
hexbin.radius = function(_) {
// ^ It is passed here
// ...
};
On the next line r = +_; + infront casts that variable (_) to a number or integer value and assigns it to variable r
DO NOT CONFUSE IT WITH += operator
=+ are actually two operators = is assignment and + and _ is variable name.
like:
i = + 5;
or
j = + i;
or
i = + _;
My following codes will help you to show use of =+ to convert a string into int.
example:
y = +'5'
x = y +5
alert(x);
outputs 10
use: So here y is int 5 because of =+
otherwise:
y = '5'
x = y +5
alert(x);
outputs 55
Where as _ is a variable.
_ = + '5'
x = _ + 5
alert(x)
outputs 10
Additionally,
It would be interesting to know you could also achieve same thing with ~ (if string is int string (float will be round of to int))
y = ~~'5' // notice used two time ~
x = y + 5
alert(x);
also outputs 10
~ is bitwise NOT : Inverts the bits of its operand. I did twice for no change in magnitude.
It's not =+. In JavaScript, + means change it into number.
+'32' returns 32.
+'a' returns NaN.
So you may use isNaN() to check if it can be changed into number.
It's a sneaky one.
The important thing to understand is that the underscore character here is actually a variable name, not an operator.
The plus sign in front of that is getting the positive numerical value of underscore -- ie effectively casting the underscore variable to be an int. You could achieve the same effect with parseInt(), but the plus sign casting is likely used here because it's more concise.
And that just leaves the equals sign as just a standard variable assignment.
It's probably not deliberately written to confuse, as an experienced Javascript programmer will generally recognise underscore as a variable. But if you don't know that it is definitely very confusing. I certainly wouldn't write it like that; I'm not a fan of short meaningless variable names at the best of times -- If you want short variable names in JS code to save space, use a minifier; don't write it with short variables to start with.
= +_ will cast _ into a number.
So
var _ = "1",
r = +_;
console.log(typeof r)
would output number.
I suppose you mean r = +_;? In that case, it's conversion of the parameter to a Number. Say _ is '12.3', then +'12.3' returns 12.3. So in the quoted statement +_ is assigned to r.
_ is just a a variable name, passed as a parameter of function hexbin.radius , and + cast it into number
Let me make a exmple same like your function .
var hexbin = {},r ;
hexbin.radius = function(_) {
if (!arguments.length)
return r;
console.log( _ , typeof _ )
r = +_;
console.log( r , typeof r , isNaN(r) );
}
and run this example function .. which outputs
hexbin.radius( "1");
1 string
1 number false
hexbin.radius( 1 );
1 number
1 number false
hexbin.radius( [] );
[] object
0 number false
hexbin.radius( 'a' );
a string
NaN number true
hexbin.radius( {} );
Object {} object
NaN number true
hexbin.radius( true );
true boolean
1 number false
It Will assign new value to left side variable a number.
var a=10;
var b="asg";
var c=+a;//return 10
var d=-a;//return -10
var f="10";
var e=+b;
var g=-f;
console.log(e);//NAN
console.log(g);//-10
Simply put, +_ is equivalent to using the Number() constructor.
In fact, it even works on dates:
var d = new Date('03/27/2014');
console.log(Number(d)) // returns 1395903600000
console.log(+d) // returns 1395903600000
DEMO:
http://jsfiddle.net/dirtyd77/GCLjd/
More information can also be found on MDN - Unary plus (+) section:
The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number. It can convert string representations of integers and floats, as well as the non-string values true, false, and null. Integers in both decimal and hexadecimal ("0x"-prefixed) formats are supported. Negative numbers are supported (though not for hex). If it cannot parse a particular value, it will evaluate to NaN.
+_ is almost equivalent of parseFloat(_) . Observe that parseInt will stop at non numeric character such as dot, whereas parshFloat will not.
EXP:
parseFloat(2.4) = 2.4
vs
parseInt(2.4) = 2
vs
+"2.4" = 2.4
Exp:
var _ = "3";
_ = +_;
console.log(_); // will show an integer 3
Very few differences:
Empty string "" evaluates to a 0, while parseInt() evaluates to NaN
For more info look here: parseInt vs unary plus - when to use which
In this expression:
r = +_;
'+' acts here as an unary operator that tries to convert the value of the right operand. It doesn't convert the operand but the evaluated value. So _ will stay "1" if it was so originally but the r will become pure number.
Consider these cases whether one wants to apply the + for numeric conversion
+"-0" // 0, not -0
+"1" //1
+"-1" // -1
+"" // 0, in JS "" is converted to 0
+null // 0, in JS null is converted to 0
+undefined // NaN
+"yack!" // NaN
+"NaN" //NaN
+"3.14" // 3.14
var _ = "1"; +_;_ // "1"
var _ = "1"; +_;!!_ //true
var _ = "0"; +_;!!_ //true
var _ = null; +_;!!_ //false
Though, it's the fastest numeric converter I'd hardly recommend one to overuse it if make use of at all. parseInt/parseFloat are good more readable alternatives.
I am trying to understand the core of JavaScript. I know it doesnt have much implementation value. If you dont want to answer, just leave it. However, I will appreciate if you could help to understand the following type coercion while applying addition(+).
1.
null + null // 0
2.
null + undefined; // NaN
3.
null + NaN; // NaN
4.
1 + null; //1
5.
true + null; //1
6.
true + [null]; //"true"
I know null is an empty or missing object. I will appreciate, if you can explain steps in type coercion or unary(+) operation here. Thanks for reading the question.
This is covered in 11.6.1 The Addition operator ( + ) - feel free to read it and follow the rules.
The first five cases can be explained by looking at ToNumber:
Value ToNumber(Value)
--------- ---------------
null 0
undefined NaN
NaN NaN
1 1
true 1
And 0 + 0 == 0 (and 1 + 0 == 1), while x + NaN or NaN + x evaluates to NaN. Since every value above is also a primitive, ToPrimitive(x) evaluates to x (where x is not a string) and the "string concatenation clause" was not invoked.
The final case is different in that it results from the ToPrimitive (which ends up calling Array.prototype.toString) on the array which results in a string value. Thus it ends up applying ToString, not ToNumber, and follows as such:
true + [null]
=> true + "" // after ToPrimitive([null]) => ""
=> "true" + "" // after ToString(true) => "true"
=> "true" // via String Concatenation
Conclusions derived from analysing results
true coerces to 1 (and false to 0).
null coerces to 0.
undefined coerces to NaN.
Arrays behave as:
under unary + (+[]):
their first element if length is 1
0 if they're empty
NaN if there's more than 1 element
under binary + (1+[]):
coerces both operators to strings and joins them
All operations on NaN return NaN
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'
This question already has an answer here:
(![]+[])[+[]]... Explain why this works
(1 answer)
Closed 7 years ago.
I came across this Javascript snippet:
var sum = +((!+[] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![]));
This example evaluates to 36.
What is happening here and what's the best way to understand/read it?
!! is a way to convert to a Boolean being either true or false. A numerical representation for true is 1 and for false it's 0. So for example:
!![] => true => 1
When you convert +[] to a number it goes to 0 (when converted to a Boolean it's false), so !+[] is true. Now lets convert those items:
var sum = +((!+[] + !![] + !![] + []) + (!+[] + !![] + !![] + !![] + !![] + !![]));
var sum = +((true + true + true + []) + (true + true + true + true + true + true));
var sum = +((3 + []) + (6));
Now note (3 + []) => "3", evals to a string. Then the string is concatenated with the number 6:
var sum = +("3" + 6); // "36"
Then finally the +("36") turns the string into a number:
var sum = 36;
There are three major things to undertand in this particular example:
What is the nature and behavior of the unary + operator
What is the nature and behavior of the logical NOT operator
How the aforementioned operators interact with empty arrays
The unary + operator converts its operand (the value to its right) to a number. The logical NOT operator either converts its operand to a boolean, or flips the value if the operand is already a boolean.
Both of these operators initially get the value of the operand before doing anything. So when the operand is an array, we need to understand what the value of the array is.
Lets try a few things first to explore how these operators behave with an array:
+[]; // 0
![]; // false
The + operator gets the value of its operand, and then converts that to a number. The ! operator gets the value of its operand, and then converts that to a boolean.
What if we were to use the ! operator twice, and use the + operator on that resulting value?
!![]; // true
+!![]; // 1
Now we're seeing the ability to create both the number 0, and the number 1. Given this power, we can begin to do some arithmetic (note that I am using the grouping operator for legibility:
(+!![]) + (+!![])
This results in 1 + 1, equaling 2. Performing operations like these enough to achieve 36 would require quite a bit of clutter, but the example above leverages the Addition Operator as a short cut.
The addition operator performs string concatenation, as well as numerical addition. So "foo"+"bar" returns "foobar". Likewise, numbers in string-form will be concatenated, rather than added: "3"+"6" returns "36". The code provided in the question achieves number to string conversion by leveraging the inherent behavior of arrays:
["Hello"].toString(); // "Hello"
[].toString(); // ""
With the addition operator, if any side of the operand is a string, the result will also be a string (see step 7 of 11.6.1). Because the array's .toString method is called, the array produces an empty string. When this string is added to a type of number, a string of that number results:
7 + ""; // "7"
This can be leveraged to concatenate, rather than add, two numbers. In the following example, I adopted our previous code that resulted in 2, and added a couple more grouping operators for legibility:
( ( +!![] ) + [] ) + ( ( +!![] ) + [] ) // "11"
On the left-hand side of the middle + operator we generate the number one, and add it to the string produced by an empty array. We then do the same thing to the value on the right-hand side of the middle + operator. The result, two strings with the value "1". The middle operator then concatenates these two strings, yielding "11".
Given this knowledge, you should be able to revisit the code in your question, and quickly make sense of the individual portions.