Created
April 22, 2014 12:55
-
-
Save radupotop/11178002 to your computer and use it in GitHub Desktop.
Interview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
1. Whats the difference between a local and a global variable. Implement a bug that could be | |
caused by accidentally forgetting to var a local variable | |
*/ | |
/** | |
A global variable is found in the global scope, eg. the window object, and can | |
be accessed from any other scope. | |
A local variable is contained within the scope of a function and can only be | |
accessed from that scope or from child scopes. | |
*/ | |
var i = 42; | |
function fn() { | |
for (i=0; i<10; i++) { | |
// ... | |
} | |
} | |
> i | |
42 | |
> fn() | |
> i | |
10 | |
/* | |
2. What does it mean to say that functions in javascript are first class objects. | |
*/ | |
/** | |
In JS functions are objects (of type Function) and can be manipulated like any | |
other object: | |
- can be passed as arguments | |
- can have properties | |
- can have methods (apply, bind) | |
- can be stored in a variable | |
- can be returned | |
*/ | |
> Function instanceof Object | |
true | |
/* | |
3. You want to quickly search for an object within a large nested data structure, is there any | |
advantage to using $.each() over traditional javascript for loops. | |
*/ | |
/** | |
An advantage would be the ability to iterate over both Arrays and Objects using | |
an uniform interface. | |
From a performance point of view there is not much difference. | |
jQuery.each caches the length in case of `for` loops over Arrays, but that is not | |
much of an improvement since modern JSVMs can optimize that loop. | |
*/ | |
/* | |
4. You see a piece of existing code. A javascript object, with curly braces, and an Array | |
declaration, both have commas after the last entry. Is this valid javascript, what are the effects | |
this will have on the code. | |
*/ | |
var hash = { a:1, b:2, c:3, }; | |
var list = [1,2,3,]; | |
/** | |
It is valid javascript. | |
However, the hash declaration will give an error in older versions of IE | |
such as 6 and 7, because of the trailing comma (it is expecting another element). | |
In other browsers the hash will create an object with 3 properties as expected. | |
In the case of the list, some browsers like Chrome and Firefox will create a list | |
with length = 3 while IE will create a list with length = 4. | |
While a list like [1,2,3,,,] will have a length of 5 in both Chrome and Firefox. | |
*/ | |
/* | |
5. Explain how javascript prototypical inheritance differs from classical inheritance. Implement | |
a subclass using javascript using the following API and test script | |
ParentClass::firstMethod(args...) | |
ParentClass::secondMethod(args...) | |
ChildClass::secondMethod(args...) // calls | |
ParentClass::secondMethod(args...) | |
parentClass = new ParentClass(); | |
childClass = new ChildClass(); | |
parentClass.firstMethod(1,2); // expect console.log('firstMethod 1'); | |
parentClass.secondMethod(1,2); // expect console.log('secondMethod 2'); | |
childClass.secondMethod(3,4); // expect console.log('secondMethod 4'); | |
console.log('thirdMethod 3'); | |
*/ | |
/** | |
Instead of inheriting from a base class, JS object instances inherit from a | |
prototype object. | |
The prototype is referenced by every new instance of the object. | |
An object can have its own properties/methods and properties/methods | |
inherited from the prototype. | |
JS uses prototype chains: object instance C can have as prototype | |
object instance B which has as prototype object instance A. | |
A property lookup traverses the prototype chain upwards. | |
*/ | |
/** | |
* Declare methods on the parent class' prototype | |
*/ | |
function ParentClass() {} | |
ParentClass.prototype = { | |
firstMethod: function(a,b) { | |
console.log('firstMethod', a); | |
}, | |
secondMethod: function(a,b) { | |
console.log('secondMethod', b); | |
} | |
}; | |
/** | |
* The child class will inherit from the parent class. | |
*/ | |
function ChildClass() {} | |
ChildClass.prototype = new ParentClass(); | |
/** | |
* Create instances of each | |
*/ | |
parentClass = new ParentClass(); | |
childClass = new ChildClass(); | |
> childClass instanceof ParentClass | |
true | |
/** | |
* Test | |
*/ | |
parentClass.firstMethod(1,2); // console.log('firstMethod 1'); | |
parentClass.secondMethod(1,2); // console.log('secondMethod 2'); | |
childClass.secondMethod(3,4); // console.log('secondMethod 4'); | |
/* | |
6. You have an interface with a series of buttons that load content into a single div. There is a | |
bug report that sometimes when a user has clicked a series of buttons, the content from the | |
wrong button has loaded into the div. Why has this happened and how would you fix it. | |
Implement your fix in the below code snippet: | |
<button onclick="onClick('A.html')">A</button> | |
<button onclick="onClick('B.html')">B</button> | |
<div></div> | |
<script> | |
var onClick = function(url) { | |
$.get(url, function(html) { | |
$('div').html(html); | |
} | |
} | |
</script> | |
*/ | |
/** | |
This is a race condition between the two asynchronous requests. | |
One response can take longer to complete than the other. | |
We can fix this by chaining the XHR requests. | |
In jQuery that would be: | |
*/ | |
var request; | |
var onClick = function(url) { | |
if(request) { | |
request = request.always(function() { | |
return $.get(url, function(html) { | |
$('div').html(html); | |
}; | |
}) | |
} else { | |
request = $.get(url, function(html) { | |
$('div').html(html); | |
}; | |
} | |
}; | |
/** | |
An approach which I like more would be using a chain of promises in AngularJS: | |
*/ | |
/** | |
* Declare an initial promise that always resolves so that we have an | |
* unifom interface. | |
*/ | |
var Defer = $q.defer(); | |
Defer.resolve(); | |
var Promise = Defer.promise; | |
/** | |
* Chain HTTP requests | |
*/ | |
function onClick(url) { | |
Promise = Promise.then(function() { | |
return $http.get(url).then(function(resp) { | |
$('div').html(resp.data); | |
}); | |
}); | |
return Promise; | |
} | |
/** | |
* I wrote a bit about promises in AngularJS here: | |
* http://wooptoo.com/blog/promises-in-angularjs/ | |
*/ | |
/* | |
7a. You have a function that is computationally expensive, but always returns the same | |
answer for a given input. You can't modify the original expensiveFunction code. Implement a | |
wrapper function to replace the original expensiveFunction variable, that caches the output | |
after the first execution. | |
*/ | |
var expensiveFunction = function( arg ) { | |
return { answer: { deep: Math.pow(arg,2) }}; // expensive | |
}; | |
/** | |
* Alias the original function to _expFn | |
* and override the original with our cacheFn | |
*/ | |
var _expFn = expensiveFunction; | |
var expensiveFunction = cacheFn; | |
function md5sum(){}; // blackbox | |
var cache = {}; | |
/** | |
* Always check for a cached result before running the expensive function | |
*/ | |
function cacheFn(arg) { | |
var argChecksum = md5sum(arg); | |
if(!cache[argChecksum]) { | |
cache[argChecksum] = _expFn(arg); | |
} | |
return cache[argChecksum]; | |
} | |
/* | |
7b. Your application code calls the above function then modifies the value returned. What will | |
be returned if you call the cached version of expensiveFunction() again? How could you avoid | |
this? What difference would this make if expensiveFunction() function simply returned a String | |
or a Number? | |
cached = expensiveFunction(); | |
cached.answer = 42; | |
test = expensiveFunction(); | |
test.answer == ??? | |
*/ | |
/** | |
If the function returns a primitive such as a Number or a String then we can | |
safely alter that value without mangling the cache. Primitives are assigned | |
by value. | |
If the returned value is an Object then altering any of its properties will | |
mangle the cache. Objects are assigned by reference. | |
We can avoid this by deep copying the result using the `extend` function from | |
point 8. | |
*/ | |
/* | |
8. Whats the difference between a deep clone and a shallow clone with a javascript | |
object. Implement jQuery.extend(true, obj1, obj2) for deep cloning. | |
*/ | |
/** | |
A shallow clone will only copy references to objects. | |
A deep clone will have its own copies of every object from the original source, | |
except Functions, since they are immutable. | |
*/ | |
/** | |
* Does a deep clone by default. | |
* Recurse into objects until hitting primitives and copying those by value. | |
* | |
* extend(dest, src1, src2...) | |
*/ | |
function extend(dest) { | |
$.each(arguments, function(i, arg){ | |
if (arg !== dest) { | |
$.each(arg, function(key, value){ | |
if($.isPlainObject(value)) { | |
dest[key] = dest[key] || {}; | |
extend(dest[key], value); | |
} else { | |
dest[key] = value; | |
} | |
}); | |
} | |
}); | |
return dest; | |
} | |
/** | |
* Test | |
*/ | |
a={}; | |
b={'name': 'Anne'}; | |
c={ | |
'action': 'has', | |
'fruit': ['apples', 'oranges'], | |
'other': { | |
'test1': 1, | |
'test2': 123, | |
'test3': { | |
'key': 'value', | |
'array': [5,6,7] | |
} | |
} | |
}; | |
extend(a,b,c); | |
/* | |
9. Describe the javascript thread model and how it interacts with setTimeout(function(){},0) | |
*/ | |
/** | |
JS runs in a single thread. The main code runs inside an event loop. | |
Asynchronous events are appended to an event queue. | |
On each loop tick a certain number of operations will be run (consumed from the queue). | |
Some operations can be expensive (can block the main thread). | |
With setTimeout(fn, 0) a function can be triggered to run in the next tick of the event loop, | |
and computationally expensive operations can be split into chunks. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment