Meebo Javascript Developer Test

I do love me these tests. They're always kinda tricky and you'll often get a good brain teaser. The PayPal one kept my house entertained for a week and the Vicious Cycle one has still got me stumped.

  1. When does div.setAttribute('attr', val) not equal div.attr = val?

    I don't normally use the div.attr shorthand because I find code more readable the more explicit it is. That said, I have to use it to set the class attribute because in IE6, styles are not applied when the class attribute is set with setAttribute. The coloring of the following table is dynamic, and looks different in IE and non-crappy browsers.

    this.setAttribute('class', this.className + ' passed')
    this.class += " passed"
    this.className += ' passed'
    this.className = 'passed'
    this.style = "background-color: green"
    this.setAttribute('style', 'background-color: green')
    this.style.setProperty('background-color', 'green', null)
    this.style.backgroundColor = 'green'
    this.id = "passedtest"
    this.setAttribute('id', 'passedtest')
  2. What's the difference between these two statements:

    1. var x = 3;
    2. x = 3;

    The first operates on the local scope, the second on the closest containing scope (frequently the global namespace). If a var x has been defined between this scope and the global scope, this function will affect that instance.

    Scoping in javascript is funky anyhow, I think a good question on an in-person exam would be, "What does this print? Assume debug() handles the display."

    var x = 3;
    (function() { x = 6; var x = 5; })();
    debug("x = " + x);
    y = 3;
    (function() { y = 13; })();
    debug("y = " + y);
    if(true) { var z = 23; }
    debug("z = " + z);

    Some people would know that the if blocks don't create a new scope like most other languages with C-esque syntax. It'd be a more rare one to know that the var x after the assignment of x makes variable local for the entire function, so the output is x = 3, y = 13, z = 23.

  3. What's the difference between:

    1. !!(obj1 && obj2)
    2. (obj1 && obj2)
    aba && b!!(a && b)
    truetrue
    truefalse
    falsetrue
    trueundefined
    true0
    true1
    trueNaN
    11
    010
    100
    00
    10"test"
    """test"

    Many kudos to Nikolas Coukouma for the answer on this one. I did not know that in javascript conditions evaluate to the first false term or the last term if all are true, so (a && b) == (a ? b : a). (I actually learned it later in the week from Douglas Crockford.) The double negation coerces it into being a boolean.

    You'll also note that NaN !== NaN.

  4. Write a one-line piece of JavaScript code that concatenates all strings passed into a function:

    function concatenate(/* any number of strings */) {
      var string = /* your one line here */
      return string;
    }

    I'm wondering if whoever wrote this assumed that arguments is a real array and therefore someone could do:

    return arguments.join('');

    That would be nice, but it isn't a real array, it has indices like an array, but it doesn't have push or pop or any of those niceties. This can be done in one pseudo-line though using an inline function:

    return (function(args) { var val = "";
                             for(i = 0; i < args.length; i++) { val += args[i]; }
                             return val; })(arguments);
    return (function(args) { var arr = new Array();
                             for(i = 0; i < args.length; i++) { arr.push(args[i]); }
                             return arr.join(''); })(arguments);

    Javascript doesn't have a lambda operator, but another option is to do something a little more functional:

    return (function(args, idx) { return (idx < args.length ?
                                          args[idx] + arguments.callee(args, idx + 1) :
                                          "") })(arguments, 0);

    I'm curious about the different performance characteristics of these solutions, but not so interested that I would write something like Jason Orendorff. Maybe someday he'll make those functions more easily accessible.

  5. What do these two examples have in common?

    1. var obj = document.getElementById('adiv');
      document.getElementById('adiv').ptr = obj;
    2. function assignClick() {
        var el = document.createElement('div');
        function handleClick() { el.innerHTML = 'clicked!'; }
        el.attachEvent('onclick', handleClick);
      }

    The answer for this one also comes from Nikolas Coukouma. I hate IE and only work in it enough to get things to work like they do in Firefox, so I didn't know that the div.ptr = obj assignment would create an element attribute in IE. Knowing that the answer is simple, that the behavior of these two snippets is significantly different in IE and W3C compliant browsers.

    In retrospect, I should have guessed this since the second one will obviously only work in IE and seemed incredibily sloppy that they would include a piece of IE only code in their test.