πŸ“œ ⬆️ ⬇️

Javascript: check your intuition


After the New Year holidays, I already suggested to the community to warm up with puzzling situations in JavaScript. Since that post, a decent amount of time has passed, there have been many other holidays, so I suggest we think about a new portion of the tasks.

Answers and my own explanation of why this behavior is logical, like last time, I will hide under the spoiler. Immediately make a reservation that I do not pretend to the unshakable truth of my versions and I will be glad to discuss them. An excellent Russian translation of the ECMAScript 5 specification can help you to solve this problem , for which many thanks iliakan !

1. The main question of life, the universe and all that.

"3" -+-+-+ "1" + "1" / "3" * "6" + "2" 

Decision
 "3" -+-+-+ "1" + "1" / "3" * "6" + "2" == "42" 

As we already know from the last post, the β€œ+” operator performs either string concatenation, addition, or coercion to a number. Those.
 β€œ3” + 2 == β€œ32” 

not 5, as one might think.
')
In addition, you can throw a unary β€œ+” or β€œ-” operator on an expression to change its sign and make things more beautiful and readable.

With all this in mind:
 + β€œ1” === 1 -+ β€œ1” === -1 +-+ β€œ1” === -1 … -+-+-+ === -1 "3" -+-+-+ "1" === 2 //    


Then we recall the priority of operations: / * +
 β€œ1”/”3” === 0.3333… β€œ1” / ”3” * ”6” === 2 2 + 2 === 4 4 + β€œ2” === β€œ42” 



2. Maximalism

 Math.max(3, 0); Math.max(3, {}); Math.max(3, []); Math.max(-1, [1]); Math.max(-1, [1, 4]); Math.max(3, true); Math.max(3, 'foo'); Math.max(-1, null); Math.max(-1, undefined); 

Decision
 Math.max(3, 0); // 3 

It's simple.

 Math.max(3, {}); // NaN 

try to execute toNumber for {}:
let's execute valueOf and check whether it is primitive - no, then
execute toString and get "[object Object]" ;
execute the resulting string toNumber and get NaN ;
in the case of obtaining NaN, Math.max () always returns NaN .

 Math.max(3, []); // 3 

try to execute toNumber for []:
let's execute valueOf and check whether it is primitive - no, then
run toString and get "";
execute the resulting string toNumber and get 0;
3> 0

 Math.max(-1, [1]); // 1 

Try to execute toNumber for [1]:
let's execute valueOf and check whether it is primitive - no, then
execute toString and get "1";
execute the resulting string toNumber and get 1;
-1 <1

 Math.max(-1, [1, 4]); // NaN 

try to execute toNumber for [1,4]:
let's execute valueOf and check whether it is primitive - no, then
execute toString and get "1,4";
execute the resulting string toNumber and get NaN ;
in the case of obtaining NaN, Math.max () always returns NaN .

 Math.max(3, true); // 3 

try to execute toNumber for true :
let's execute valueOf and check whether it is primitive - yes, then
 toNumber(true) === 1 

3> 1

 Math.max(3, 'foo'); // NaN 

for 'foo' toNumber returns NaN .
In the case of getting NaN, Math.max () always returns NaN .

 Math.max(-1, null); // 0 

 toNumber(null) === 0 -1 < 0 


 Math.max(-1, undefined); // NaN 

 toNumber(undefined) === NaN 

in the case of obtaining NaN, Math.max () always returns NaN .


3. Life comma

 [,,,].join() [,,,undefined].join() 

Hidden text
 [,,,].join() // ",," [,,,undefined].join() // ",,," 

Here I can only refer to Flanagan. 7.1:
β€œIf an array literal contains several consecutive commas with no values ​​between them, a sparse array is created. The elements corresponding to these missing values ​​are missing in the array, but returning to them returns the value undefined. ”
"The syntax of array literals allows you to insert an optional trailing comma."
Why is this done I do not understand. In comments to the last post it was presented as a feature. In my opinion, this is still a browser crutch from errors in the code.


4. Treasure Map

 Array(20).map(function(elem) { return 'a'; }); 

Hidden text
 Array(20).map(function(elem) { return 'a'; }); // Array of undefined x 20 

Calling the Array constructor with one argument creates not an array of 20 elements, but an array whose length is 20. And the map method first creates an empty array whose length equals the length of the passed array, and then calls a callback for each element of the passed array. In our case, the array has no elements and the method returns an empty array of the same length as the original one.


5. Finita la comedia

 isFinite(42); isFinite(1/0); isFinite(0/0); isFinite('42'); isFinite('hi'); isFinite(); isFinite(undefined); isFinite(null); 

Hidden text
 isFinite(42); // true isFinite(1/0); // false isFinite(0/0); // NaN is not finite -> false isFinite('42'); // true isFinite('hi'); // false isFinite(); // false isFinite(undefined); // false isFinite(null); // true 

isFinite leads the argument to a number, and if NaN, + Infinity or -Infinity is obtained , it returns false . In all other cases, true .
ToNumber from 'hi' returns NaN , undefined returns NaN , and null returns 0.


6. True story bro

 'true' == true 

Hidden text
 'true' == true //false 

The equality operator will sequentially lead to numbers, first true, then 'true'. It turns out NaN == 1, which is obviously false.


7. Nothingness

 null == false !null 

Hidden text
 null == false // false !null // true 

With null reduction to bool, everything is clear. We will understand the comparison. the combination of null and bool does not fall under any of the comparison / coercion options in clause 11.9.3 of the specification and therefore the comparison returns false .


8. Testing uncertainty

 /^[az]{1,10}$/.test(null); /^[az]{1,10}$/.test(undefined); 

Hidden text
 /^[az]{1,10}$/.test(null); //true /^[az]{1,10}$/.test(undefined); //true 

Null and undefined are cast to the string as is: β€œnull” and β€œundefined” - and such strings satisfy the regular expression. And NaN , by the way, will also become "NaN".


9. Negation of zero

  0 === -0 1/0 === 1/-0 

Hidden text
  0 === -0 //true 1/0 === 1/-0 //false 

Zero is equal to negative zero, but when dividing with a sign, the sign is taken into account and it turns out
 Infinity === -Infinity 



For those heroes who read to the end, perhaps the most interesting task. I do not want to hide the explanation under another spoiler, so I advise after you give an answer, open devtools and check there. It is likely that the result will surprise you and you will want to think again.
10. Slash

 n = 1 /1*"\/\//.test(n + '"//') n = 1; /1*"\/\//.test(n + '"//'); 

Hidden text
 n = 1 /1*"\/\//.test(n + '"//') //NaN n = 1; /1*"\/\//.test(n + '"//'); //true 

Slash can be used in three cases: regular expression, division, and comment. Here, at first glance, we see only the regular expression. But, in fact, without a semicolon, the first slash performs a division. Thus, the first division is performed, and then the result is multiplied by the string. The remaining tail is just a comment. The string by which we multiply to the number is not given and it turns out NaN .

Source: https://habr.com/ru/post/225405/


All Articles