JavaScript: test your intuition


    After the New Year holidays, I already invited the community to stretch their mind at jigsaw puzzles in JavaScript. Quite a lot of time has passed since that post, there have been many other holidays, so I suggest thinking about a new portion of tasks.

    I will hide the answers and my own version of the explanation of why this behavior is logical, as last time, 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. The excellent Russian translation of the ECMAScript 5 specification can help you in solving this , for which many thanks iliakan !

    1. The main issue 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 concatenation of strings, or addition, or reduction to a number. Those.
    “3” + 2 == “32”
    

    not 5, as you might think.

    In addition, you can throw the unary operator “+” or “-” on an expression to change its sign and make things more beautiful and readable.

    Given all of the above:
    + “1” === 1
    -+ “1” === -1
    +-+ “1” === -1
    …
    -+-+-+ === -1
    "3" -+-+-+ "1" === 2  //вычитание производится над числами
    


    Next, 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
    

    Everything is simple here.

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

    try to execute toNumber for {}:
    execute valueOf and check if it is primitive - no, then
    execute toString and get "[object Object]" ;
    execute for the resulting string toNumber and get NaN ;
    if NaN is received, Math.max () always returns NaN .

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

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

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

    we will try to execute toNumber for [1]: we
    will execute valueOf and we will check whether it is primitive - no, then we
    will execute toString and we will receive "1";
    execute for the resulting string toNumber and get 1;
    -1 <1

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

    try to execute toNumber for [1,4]:
    execute valueOf and check if it is primitive - no, then
    execute toString and get “1,4”;
    execute for the resulting string toNumber and get NaN ;
    if NaN is received, Math.max () always returns NaN .

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

    try to execute toNumber for true :
    execute valueOf and check if this is primitive - yes, then
    toNumber(true) === 1
    

    3> 1

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

    for 'foo' toNumber returns NaN .
    If NaN is received, Math.max () always returns NaN .

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

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


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

    toNumber(undefined) === NaN
    

    if NaN is received, 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. Elements corresponding to such missing values ​​are absent in the array, but when they are accessed, the value is undefined. "
    " The syntax of array literals allows you to insert an optional trailing comma. "
    Why is this not clear to me. In the comments on the last post, this 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 does not create an array of 20 elements, but an array with a length of 20. And the map method first creates an empty array whose length is equal to the length of the transferred array, and then calls a callback for each element of the transferred array. In our case, the array has no elements and the method returns an empty array of the same length as the original.


    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 converts the argument to a number, and if it turns out NaN, + Infinity or -Infinity , then returns false . In all other cases, true .
    ToNumber from 'hi' will return NaN , undefined will return NaN , and null will return 0.


    6. True story bro

    'true' == true
    

    Hidden text
    'true' == true //false
    

    The equality operator sequentially leads 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 casting null to bool, everything is clear. We will deal with the comparison. the combination of null and bool does not fall under any of the comparison \ cast options in clause 11.9.3 of the specification and therefore the comparison returns false .


    8. Uncertainty Testing

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

    Hidden text
    /^[a-z]{1,10}$/.test(null);  //true
    /^[a-z]{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 negative zero, but when dividing with a sign, the sign is taken into account and it turns out
    Infinity === -Infinity
    



    For those heroes who have read to the end, perhaps the most interesting puzzle. I do not want to hide the explanation under another spoiler, so I advise you after you give the 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
    

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

    Also popular now: