krystophv
9/13/2010 - 11:31 PM

screening.js

// 1: how could you rewrite the following to make it shorter?
if (foo) {
  bar.doSomething(el);
} else {
  bar.doSomethingElse(el);
}

// I think this might be considered a bad idea, as the if/else is very clear and readable.
// It's usually a good idea to keep code verbose and clear for maintainability and run it
// through a compressor for production. However, I guess if it's gotta be shorter:

foo ? bar.doSomething(el) : bar.doSomethingElse(el);




// 2: what is the faulty logic in the following code?
var foo = 'hello';

(function() {
  var foo = foo || 'world';
  console.log(foo);
})();

// The self executing function scope is outside the scope in which foo is defined,
// so inside the function, foo will always be undefined initially, and will always
// bool to false. Therefore, the variable declaration 'foo' will always assume the 
// value 'world' inside the function.



// 3: given the following code, how would you override the value of the bar
// property for the variable foo without affecting the value of the bar
// property for the variable bim? how would you affect the value of the bar
// property for both foo and bim? how would you add a method to foo and bim to
// console.log the value of each object's bar property? how would you tell if
// the object's bar property had been overridden for the particular object?
var Thinger = function() {
  return this;
};

Thinger.prototype = {
  bar : 'baz'
};

var foo = new Thinger(),
    bim = new Thinger();

// override value of foo.bar without affecting bim.bar
foo.bar = "bow";

// affect value of bar property for both foo and bim
Thinger.prototype.bar = "bow";

// add a method to foo and bim to console.log the value of each object's 
// bar property
Thinger.prototype.logBar = function(){
    console.log(this.bar);
};

// how would you tell if the object's bar property had been overridden for 
// the particular object

if(foo.bar == Thinger.prototype.bar){
    //do stuff
}


// 4: given the following code, and assuming that each defined object has a
// 'destroy' method, how would you destroy all of the objects contained in the
// myObjects object?
var myObjects = {
  thinger : new myApp.Thinger(),
  gizmo : new myApp.Gizmo(),
  widget : new myApp.Widget()
};


var object;
for(object in myObjects){
    myObjects[object].destroy();
}


// 5: given the following array, create an array that contains the contents of
// each array item repeated three times, with a space between each item. so,
// for example, if an array item is 'foo' then the new array should contain an
// array item 'foo foo foo'. (you can assume the library of your choice is
// available)
var myArray = [ 'foo', 'bar', 'baz' ];

var newArray = $.map(myArray, function(val, i){ return val+' '+val+' '+val; })


// 6: how could you improve the following code?
$(document).ready(function() {
  $('.foo #bar').css('color', 'red');
  $('.foo #bar').css('border', '1px solid blue');
  $('.foo #bar').text('new text!');
  $('.foo #bar').click(function() {
    $(this).attr('title', 'new title');
    $(this).width('100px');
  });
  
  $('.foo #bar').click();
});


// Since this seems to be a one-off, it's probably ok to improve as follows:

$(function() {
    var bar = $('#bar');

    bar.css({'color':'red',
             'border':'1px solid blue'})
       .text('new text!')
       .click(function(){
           var $this = $(this);
           $this.attr('title', 'new title')
                .width('100px');
       })
       .click();
});

// If this were being applied to a number of elements, this may not be acceptable.
// Additional improvements would be to use .detach() before the css and text as DOM
// manipulation can get slow. Also using a variable for the click handler function
// instead of an anonymous function. Might be overkill for a single element on a static
// page though.


// 7: what issues do you see with the following code? how would you fix it?
(function() {
  var foo;

  dojo.xhrGet({
    url : 'foo.php',
    load : function(resp) {
      foo = resp.foo;
    }
  });

  if (foo) {
    // run this important code
  }
})();

// The largest issue I see is that the important code is run on the conditional 
// which will most likely not be set as the xhrGet takes an indeterminate amount of time
// to return. The solution to this is to move the if block surrounding the important code
// to a function which should replace the load handler on the xhrGet, like this:

(function() {
  var fooLoad = function(resp){
          if(resp.foo){
              // run this important code
          }
      };

  dojo.xhrGet({
    url : 'foo.php',
    load : fooLoad
  });

})();



// 8: how could you rewrite the following code to make it shorter?
(function(d, $){
  $('li.foo a').attr('title', 'i am foo');
  $('li.bar a').attr('title', 'i am bar');
  $('li.baz a').attr('title', 'i am baz');
  $('li.bop a').attr('title', 'i am bop');
})(dojo, dojo.query);

(function(d, $){
  d.forEach(['foo', 'bar', 'baz', 'bop'], function(val, i){
      $('li.'+val+' a').attr('title', 'i am '+val);    
  });
})(dojo, dojo.query);



// 9: how would you improve the following code?
for (i = 0; i <= 100; i++) {
  $('#thinger').append('<p><span class="thinger">i am thinger ' + i + '</span></p>');
  $('#gizmo').append('<p><span class="gizmo">i am gizmo ' + i + '</span></p>');
}


// Iterative appends are generally slow, since it hits the DOM each time. It's best to
// generate the content you want to append first and then append once. It's even better
// to have a single parent node for the appended content, but this will probably do.

var thingerList = [], gizmoList = [], i;

for(i = 0; i <= 100; i++){
    thingerList.push('<p><span class="thinger">i am thinger ' + i + '</span></p>');
    gizmoList.push('<p><span class="gizmo">i am gizmo ' + i + '</span></p>');
}

$('#thinger').append(thingerList.join(''));
$('#gizmo').append(gizmoList.join(''));




// 10: a user enters their desired tip into a text box; the baseTotal, tax,
// and fee values are provided by the application. what are some potential
// issues with the following function for calculating the total?
function calculateTotal(baseTotal, tip, tax, fee) {
  return baseTotal + tip + tax + fee;
}

// There's no validation on the value of 'tip' from what I can see here,
// so there's no telling what might get returned, due in part to javascript's
// loose typing. Should probably verify that tip is a float with two digits
// past the decimal point. 




// 11: given the following data structure, write code that returns an array 
// containing the name of each item, followed by a comma-separated list of
// the item's extras, if it has any. e.g. 
//
//    [ "Salad (Chicken, Steak, Shrimp)", ... ]
//
// (you can assume the library of your choice is available)
var menuItems = [
  {
    id : 1,
    name : 'Salad',
    extras : [
      'Chicken', 'Steak', 'Shrimp'
    ]
  },
  
  {
    id : 2,
    name : 'Potato',
    extras : [
      'Bacon', 'Sour Cream', 'Shrimp'
    ]
  },
  
  {
    id : 3,
    name : 'Sandwich',
    extras : [
      'Turkey', 'Bacon'
    ]
  },
  
  {
    id : 4,
    name : 'Bread'
  }
];


$.map(menuItems, function(item, index){
    var ret = item.name;
    
    if(item.extras){
        ret += " (" + item.extras.join(', ') + ")";
    }
    return ret;
});



// BONUS: write code such that the following alerts "Hello World"
say('Hello')('World');

// Well, the following works, but I think it defeats the point as it 
// only works for a very narrowly defined case:
 
function say(text){
    if(text == "World"){
        alert("Hello World");
    }
    else{
        return say
    }
}

// The following is a little more robust, but only works with a two
// function chain:

function say(text, addTo){
    if(addTo){
        text = addTo + ' ' + text;
        alert(text);
    }
    else{
        return function(more){
            return say(more, text)
        }
    }
}

// I'm sure there's a general solution, but the proxying of the methods
// and determining which of the calls should ultimately call the alert()
// (presumably the last in the chain) might be beyond me

// BONUS: what is the faulty logic in the following code? how would you fix it?
var date = new Date(),
    day = date.getDate(),
    month = date.getMonth(),
    dates = [];
    
for (var i = 0; i <= 5; i++) {
  dates.push(month + '/' + (day + i));
}

console.log('The next five days are ', dates.join(', '));


// The faulty logic is that they're not really adding a day to the current date,
// but rather to the current day of the month. The error would become evident when
// you get near the end of the month - the dates array would contain invalid dates
// (i.e 9/30, 9/31, 9/32, 9/33, 9/34) 
// Additionally, if you're going from 0 to 5 through the iteration, you'll end up
// counting today as the first of the "next five days", which isn't correct. Instead,
// counting should go from 1 to 6.
// The simplest way to fix this is to add onto the actual date object and get the month
// and day each time to ensure that you've got a valid date.

// Or you could just use Date.js and make date math nice

var date = new Date(),
    dateMS = date.getTime(),
    dates = [],
    dayDelta = 1000 * 60 * 60 * 24;

for (var i = 1; i <= 6; i++) {
  var datePlus = new Date(dateMS + i*dayDelta);
  dates.push(datePlus.getMonth() + '/' + datePlus.getDate());
}

console.log('The next five days are ', dates.join(', '));


/*
          DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
                   Version 2, December 2004 

Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> 

Everyone is permitted to copy and distribute verbatim or modified 
copies of this license document, and changing it is allowed as long 
as the name is changed. 

           DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 

 0. You just DO WHAT THE FUCK YOU WANT TO.
*/