implicit getElementById

oct 2 , 2013

document.getElementById can be omitted in all major browsers, inclunding IE6+. This is non-standard, but all of them save the elements ids as globals.

    <div id="myId"></div>
    <script>
      alert(myId.id);         // --> myId
      alert(window.myId.id);  // --> myId
    </script>

Or do they? Let's search myId in the window object.

    // Way 1
    alert('myId' in window);  // --> true (right...)
    // Way 2
    var present = false;
    for(var i in window){
      if(i == 'myId'){
        present = true;
      }
    }
    alert(present);           // --> false (wat!)

Looks like all browsers create Shroedinger's globals, that are here and not here at the same time...

What happens to globals when an element with the same id is created?

    <script>
      global0 = 1;
    </script>

    <div id=global0></div>

    <script>
      global0.innerHTML = "global0";     // --> nothing happens
      alert(global0);                    // --> 1
    </script>

So implicit getElementById's can't overload global vars, be they native or custom. What about the other way? Well, it depends on how the global var is set.

Let's try with "window."

    <div id=global1></div>

    <script>
      global1.innerHTML = "global1";        // --> the div is updated
      console.log(global1);                 // --> the div
      window.global1 = 1;                   // Try to set the global var "global1"
      console.log(global1);                 // --> 1
    </script>

OK.

Let's try without any prefix.

    <div id=global2></div>

    <script>
      global2.innerHTML = "global2";    // --> the div is updated
      try{global2 = 1}                  // Try to set the global var "global2"
      catch(e){alert(e)}                // --> TypeError on IE < 9, ok on other browsers
      global2.innerHTML = "hum";        // --> div contains "hum" on IE < 9, nothing happens on other browsers
      console.log(global2);             // --> "[object]" on IE < 9, 1 on other browsers
    </script>

Weird.

And what happens if the global var is declared with "var" ?

    <div id=global3></div>

    <script>
      global3.innerHTML = "global3";    // --> Uncaught TypeError: Cannot set property 'innerHTML' of undefined (wtf...)
      console.log(global3);             // --> undefined (wtf?)
      var global3 = 1;                  // --> this breaks the two lines above (wtf!)
      console.log(global3);             // --> 1
    </script>

WAT.

@MaximeEuziere


Array Constructor2 is Very Undefined

sept 30 , 2013

Have you ever thought that Array(3) will return you an array of 3 undefined's, the same as [undefined,undefined,undefined]?

So try this:

    Array(3).forEach(function(elem) { console.log(elem); });

And you will get no result at all, however

    [undefined,undefined,undefined].forEach(function(elem) { console.log(elem); });

will give you 3 nice log entries.

Are the first example's undefined less defined than the second example's undefineds?

Not really. According to forEach spec: "callbackfn is called only for elements of the array which actually exist", and constructor spec says nothing about putting in any elements (even undefined).

@tomalec


Math.max() behaviour

aug 7 , 2013

Math.max() has an interesting behaviour, handling different JavaScript data types in different ways.


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

Now, let's focus on Booleans:


    Math.max(1, true);     // 1
    Math.max(0, true);     // 1
    Math.max(1, false);    // 1
    Math.max(-1, true);    // 1
    Math.max(-1, false);   // 0

And now, on Arrays:


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

So next time, watch out for what you pass into Math.max().

@gnclmorais

Math.max() typecasts all values to Numbers (Number(x)), e.g.:

Math.max(false, -1); // 0
Math.max(5, "10");   // 10

@ixti


array ruse

july 18 , 2013
[,,,].join() // ==> ",,"

wtf?

@eliranmal

Turns out that the trailing comma is removed (trailing commas are allowed in javascript, but not JSON). Once removed, there are only three "elements" in the array, and both are undefined. When join is called, by default it uses a comma, yielding ",,". I think this is what happens

@DDTrejo

JSON has nothing to do with this issue. Although trailing comma is really allowed by Javascript and that's the case. So [1,2,3,] equals to [1,2,3]. So literally [,,,] is something like [undefined, undefined, undefined,]. You can add undefined to the end explicitly to get 4 elements array:

[,,,undefined].join() // ==> ',,,'

@ixti


Fork me on GitHub