The quirks of JavaScript

Developers from my team come up with a rather interesting challenge to produce a small piece of JavaScript code of which output would be impossible to predict for a non-JS developer. Obviously we're talking about human-readable i.e. no obfuscation. Here is what we've came up:

(function() {
    logMe();
    var logMe = function() {
        console.log('Jesus, George, it was a wonder I was even born.');
    };
    logMe();

    function logMe() {
        console.log('Great Scott!');
    }
    logMe();

    console.log(parseInt('010'));
})();

Can you predict the output? You can find some good hints in my article listing common JavaScript interview questions.

You can check your result here (I've spiced the code with some jQuery DOM manipulation for better readability):

http://jsfiddle.net/tnajdek/vwAg9/ If your reaction was similar to "WTF?!", here is the same code with some comments:

(function() {
	// this is where second logMe definition has been hoisted

	logMe(); // logMe function definition has been hoisted 
		 // at this stage exists as per *second* definition

	var logMe = function() { 

		// variable logMe is being hoisted to the top of the scope
		// however only the definition of the variable is being hoisted,
		// value (which happened to be a function) assignment is not!

		console.log('Jesus, George, it was a wonder I was even born.');
	};

	logMe(); // logMe has been defined and it's value assigned above
		 // hence this now uses *first* definition of the function

	function logMe() {
		// function declarations are hoisted together with its body
		// When interpreted this code moves to the top of the 
		console.log('Great Scott!');
	}
	logMe(); // *second* declaration has been hoisted 
		 // so this call is identical as the logMe called above

	// parseInt function is hard to predict 
	// when second (optional) argument is not specified
	// see my explanation note below

	console.log(parseInt('010'));

})();

Unpredictability of this code is achieved with 2 JavaScript quirks: Hoisting (which is explained in my JS interview questions article) and unexpected behaviour of the parseInt method: JavaScript will try to "guess" a correct value of radix argument if none is provided and if the first argument happens to begin with "0" it will assume radix = 8 (octal) henceparseint('010') == 8. It's well covered in the relevant Mozilla Developer Network, the most important bit being:

If radix is undefined or 0, JavaScript assumes the following: If the input string begins with "0x" or "0X", radix is 16 (hexadecimal). If the input string begins with "0", radix is eight (octal). This feature is non-standard, and some implementations deliberately do not support it (instead using the radix 10). For this reason always specify a radix when using parseInt. If the input string begins with any other value, the radix is 10 (decimal).

For sake of code readability and to help yourself and others who might need to work with your code, please use jslint or jshint and avoid spaghetti code as the one above. Both tools will help you avoid problems with hoisting and will ask you to specify radix. Thank you.