How does this code work? I would like a detailed explanation if possible and to know where there is documentation about it.
if (!+[]+!+[] == 2) {
document.write('Somos iguales');
}
else {
document.write('Somos distintos');
}
How does this code work? I would like a detailed explanation if possible and to know where there is documentation about it.
if (!+[]+!+[] == 2) {
document.write('Somos iguales');
}
else {
document.write('Somos distintos');
}
An
Array
empty is equal tofalse
the opposite of
false
istrue
true
is equal to 1,false
is equal to 0then
JSFuck
is an esoteric and educational programming style based on the atomic parts of JavaScript .Some rules to remember:
Preceding with
!
convert to valueBooleano
Preceding with we
+
convert to numberAddition
[]
convert to String!+[]
by putting the plus sign before it becomes a number ,+[] = 0
the negation(!)
of 0 is 1.Then when performing the sum
!+[] + !+[]
that is1+1 = 2
References
Listed below are the references corresponding to each of the main parts of
Which are
[]
expression to initialize an object literal of type array, equivalent tonew Array()
.+[]
matrix with unary operator +.!+[]
matrix with unary operator + and non-logical unary operator.!+[] + !+[]
addition of two!+[]
.!+[] + !+[] == 2
abstract comparison of the addition of two!+[]
.Let us begin
[]
initializes an array literal with no elements. The length property (length
) of the array is zero. and the primitive value is an empty string. For more details see the answer to What is the primitive value of [] based on ECMAScript 2016 (version 7)? .In Unary + operator 1 it is indicated that it
+
converts its operand to type number. In the case of+ []
, the operand is an empty string (testing[].join() === ''
in the Chrome console returnstrue
) and converting this to a number converts to0
.In logical operator not 1 it is indicated that it
!
converts its operand to boolean type, and that if the boolean value of the operand is false, it returns true and if the boolean value of the operand is true, it returns false.In ToBoolean 1 it is indicated that when the value is zero (
-0
or+0
), false (false
) is returned.In The Addition Operator ( + ) 1 it is indicated that when the operands are of a type other than a text string, they are converted to a number.
ToNumber 1 indicates that when the value is true, one ( ) is returned, and when the value is false, zero ( ) is returned.
1
0
In Applying the Additive Operators to Numbers 1 it is indicated that when
+
it is applied to two numeric operands, it performs the addition of these.In Abstract equality comparison 1 it is indicated that when the two elements on the left and right are equal, it returns true (
true
) and otherwise it returns false (false
).Then
+[]
is a unitary operation that returns zero (0
)!0
is a unitary operation that returns true (true
)true + true
is an operation that first converts each operand to1
and then returns its addition which is2
2 == 2
is an abstract equality comparison that returns true (true
)Here is a little experiment for the reader to check if stack-snippet and their browser operate according to the referenced specification.
To complement the answers, let us consider the following series of additional elements documented in:
1) JavaScript primitive and complex data:
JavaScript bases its data types on ECMAScript, divided into primitive and complex or referenced:
Primitive data:
String : unicode, ascii and alphanumeric characters.
Number : integer, float.
Boolean : true and false.
Null : null.
Undefined : undefined.
Complex data:
2) Boolean values of the data:
Primitive data:
var string="Hola soy una string";
will returntrue
.var integer=123;
will returntrue
.var trueVariable = true;
will returntrue
.var float = 4.98;
will return true.Complex data:
var arraySinElementos = [];
will returntrue
.var arrayConElementos = [0,1,2];
will returntrue
.Exceptions :
Based on the aforementioned table we can find the Boolean values of the following data types, by applying
ToBoolean()
:Boolean false : will return
false
.Number zero : will return false.
Undefined : will return false.
Null : will return false.
2) Value of the logical operators:
We define the main logical values:
Logical operator
not (!)
: applies the inverse of the received value.Its operation would be as follows:
The expression will be evaluated with a
ToBoolean()
, which will follow the following table:Applying the inverse we will have:
In the case of being the expression,
true
it will returnfalse
.In the case of being, it will be
false
returnedtrue
.If it is nonzero (
!==0
), the result is zero.If it is 0 the result will be 1.
Strings are converted to numbers, if possible.
Empty strings are converted to
true
.The logical value null or not performs the action of determined
false
, since it is not known if the condition is true.3) Unary plus operator (+ expression) and addition plus operator (expression + expression):
The plus (+) operator can be found as a unary and addition operator :
This function will apply
ToNumber()
to the expression:If it is used on a non-numeric value it will apply the function
ToNumber()
, in our case we have aarray[]
that would enter the referenced data orObject
.In other words, it
ToNumber()
will be applied to aobject
, therefore the use ofToPrimitive()
.4) Function
ToPrimitive()
:This function is found in the type conversion section:
And it will be used in order to convert the object
Object
to a primitive value so that it can be later evaluated with:Respectively.
In this case, being an Object
Object
: applies:Following the following order of evaluation:
Summary table:
The conversion proceeds:
In this case it is a
string vacio
.Fulfilling:
Apply "
toString()
" and then "valueOf()
"Applying we have:
Therefore:
+[] == ToNumber(array[]).
ToNumber(array[]) == ( "" ).valueOf().
( "" ).valueOf == ( "" ).
Now let's use our logical operator not (!) to get:
5) Next it would be time to replace :
Solving:
Ending:
I see that this question has generated a very valuable group of answers and it is these types of questions and answers that feed our community the most. I will try to contribute my grain of sand to this wonderful thread.
I am going to clarify certain aspects that are not clarified. Whoever reads the answers will notice that there are some that contradict each other. I have seen a comment from @toledano in @Dev.Joel's answer and another from @Dev.Joel in @JorgeArturoJuarez's answer basically wondering why
[] == false
it istrue
and on the other hand it![]
isfalse
and it seems to me that it is due to several of the answers that are somewhat ambiguous, such as the answer marked as correct showing that it[]
was equal tofalse
.The first thing to know is that every instance of an object is self-defined and therefore true:
Instances of an object should not be confused with primitive values:
Sin embargo al usar los operadores de comparación (exceptuando
===
y!==
) y los operandos tener un tipado diferente,JavaScript
intenta convertir ambos operandos a un tipo apropiado para realizar la comparación, y generalmente esta conversión es numérica. Es por eso que ocurre lo siguiente sin importar que sean instancias de objetos y sean verdaderas:Teniendo esto en cuenta se podrá entender por qué
[] == false
datrue
y![]
dafalse
.En cuanto a la pregunta principal, ya todo está más que explicado en las anteriores respuestas, aquí lo resumo:
+
a una instancia deArray
vacía el resultado es0
(ya que internamente le aplica la operación abstractaToNumber
).!
a0
el resultado estrue
(ya que este operador devuelvefalse
si la expresión puede ser evaluada atrue
y en caso contrario devuelvetrue
)true
el resultado será2
(ya que al no tratarse de cadenas de caracteres, en vez de concatenar, el operador intentará convertir los operandos a número antes de sumarlos)