Javascript Skill Test

  • Found this test from the internet (Download: JavaScript_Skill_Test-blank)
  • Tried to solve without using Google. FAILED.
  • With help from Google, solved questions. There was someone’s solution for exact same questions; I resisted a lot to not see his solution. Some questions are referred  to understand what question was.
  •  If I get this test in the interview without using internet, I probably failed completely. Need more study…
  • Solution: JavaScript_Skill_Test-solution

Javascript Skill Test

Q1. Fix the below JavaScript code so that the correct index is printed to console.log on each iteration.

(function() {
	var index
	length = 10;
	for (index = 0; index < this.length; index++) {
		setTimeout(function() {
			console.log(index); 
		}, 100);
	}
}());

Solution: [HTML] The loop finishes before the first timeout;thus, it shows 10 for 10 times. Solution is pass actual value of the loop to the setTimeout function. http://stackoverflow.com/a/5226349

(function() {
	var index
	length = 10;
	for (index = 0; index < this.length; index++) {
		(function(index){
			setTimeout(function() {
				console.log(index); 
			}, 100);
		})(index);
	}
}());

Q2. Modify the below JavaScript so that it is called just after the DOM has loaded. No legacy browser support required.

(function() {
	document.getElementById("test").innerHTML = "Hello World"; 
}());

Solution[HTML]

window.onload = function() {
	document.getElementById("test").innerHTML = "Hello World"; 
};

Q3. Modify the below code so that it will only display a message if the user is using Internet Explorer 7

(function() {
	alert("Hello World"); }
)();

Solution[HTML]

<!--[if IE 7]>
<script type="text/javascript">
	(function() {
		alert("Hello World"); }
	)();
</script>
<![endif]--><span style="line-height: 1.714285714; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 1rem;">&nbsp;</span>

Q4. Finish the below JavaScript by implementing a simple flow control function (flow) that can take the provided array of functions and process them asynchronously before making a final callback.

(function() { 
	var array = [
		function(callback) {
			console.log("first function called in " + (new Date().getTime() - timestamp) + "ms");
			callback(); 
		},							
		function(callback) {
			console.log("second function called in " + (new Date().getTime() - timestamp) + "ms");
			callback(); 
		},
		function(callback) {
			console.log("third function called in " + (new Date().getTime() - timestamp) + "ms");
			callback(); 
		}
	],
	timestamp = new Date().getTime();
	
	function flow(array, callback) {
	}
	flow(array, function() {
		console.log("all functions finished in " + (new Date().getTime() - timestamp) + "ms"); 
	});
}());

Solution: [HTML]

(function() { 
	var array = [
		function(callback) {
			console.log("first function called in " + (new Date().getTime() - timestamp) + "ms");
			callback(); 
		},							
		function(callback) {
			console.log("second function called in " + (new Date().getTime() - timestamp) + "ms");
			callback(); 
		},
		function(callback) {
			console.log("third function called in " + (new Date().getTime() - timestamp) + "ms");
			callback(); 
		}
	],
	timestamp = new Date().getTime();
	
	var i = 0;
	function acallback(array_elm, index, callback)
	{
		array_elm(function(){
			if(++i == array.length)
			{
				callback();
				return;
			}
			acallback(array[i], i, callback);
		});
	}
	
	function flow(array, callback) {
		acallback(array[0], i, callback); 
	}
	flow(array, function() {
		console.log("all functions finished in " + (new Date().getTime() - timestamp) + "ms"); 
	});
}());

Q5. Modify the below code so that the return value can also be returned with a callback function (if a callback function has been specified).

(function() {
	function isArray(array) {
		return typeof(array) === "object" && (array instanceof Array);					
	}

	var result = isArray([ "item1", "item2", "item3" ]);
	console.log("isArray: " + result); 
}());

Solution[HTML]

(function() {
	function isArray(array, callback) {
		var bArray = typeof(array) === "object" && (array instanceof Array);
		if(typeof callback !== 'undefined')
		{
			callback(bArray);
		}					
		else
		{
			return bArray;
		}
	}

	var testArray = [ 
		"item1", 
		"item2", 
		"item3" 
	];
	var result = isArray(testArray, function(result){
		console.log("isArray with Callback = " + result); 
	});
	
	console.log("isArray with No callback = " + isArray(testArray));
}());

Q6. Modify the below JavaScript code so that it uses a closure to return the response.

(function() {
	function hello(name, age) {
		return name + ", who is " + age + " years old, says hi!");
	}
	console.log(hello('John', 33)); 
})();

Solution[HTML]

(function() {
	function hello(name, age) {
		return (name + ", who is " + age + " years old, says hi!");
	}
	console.log(hello('John', 33)); 
})();

Q7. Optimize the below JavaScript to minimize the number of redraws and reflows required.

(function() {
	var element,
		index,
		length,
		content = document.getElementById("content"), 
		data = [{
			id: 1,
			name: "John", 
			color: "green"
		}, {
			id: 2,
			name: "Sally", 
			color: "pink"
		}, {
			id: 3,
			name: "Andrew", 
			color: "blue"
		}, {
			id: 4,
			name: "Katie", 
			color: "purple" 
		}],
		
	for (index = 0, length = data.length; index++) {
		element = document.createElement("li"); 
		content.appendChild(element);
		element.setAttribute("id", data[index].id);
		element.innerHTML = "<strong>" + data[index].name + "</strong>"; 
		element.style.color = data[index].color;
	} 
})();

Solution: [HTML]

(function() {
	var element,
		index,
		length,
		content = document.getElementById("content"), 
		data = [{
			id: 1,
			name: "John", 
			color: "green"
		}, {
			id: 2,
			name: "Sally", 
			color: "pink"
		}, {
			id: 3,
			name: "Andrew", 
			color: "blue"
		}, {
			id: 4,
			name: "Katie", 
			color: "purple" 
		}];
	
	var html = "";
	for (index = 0; index < data.length; index++) {
		html += "<li id='"+data[index].id+"' style='color:"+data[index].color+";'><strong>"+data[index].name+"</strong></li>";
	} 
	content.innerHTML = html;
})();

Q8. Using the below JavaScript code as a starting point, implement a chain-able DOM Wrapper API that operates in a similar fashion to jQuery’s API (No native prototype extensions).

(function() {
	NodeList.prototype.show = function() {
		var array = Array.prototype.slice.call(this, 0);
		array.forEach(function(node) {
			node.style.display = "block"; 
		});
	}
	NodeList.prototype.hide = function() {
		var array = Array.prototype.slice.call(this, 0);
		array.forEach(function(node) {
			node.style.display = "none"; 
		});
	}
	document.querySelectorAll("#test").show(); 
	document.querySelectorAll("#test").hide(); 
}());

Solution[HTML]

(function() {
	// Extend native javascript objects
	NodeList.prototype.show = function() {
		var array = Array.prototype.slice.call(this, 0);
		array.forEach(function(node) {
			node.style.display = "block"; 
		});
		return this;
	};
	NodeList.prototype.hide = function() {
		var array = Array.prototype.slice.call(this, 0);
		array.forEach(function(node) {
			node.style.display = "none"; 
		});
		return this;
	};
	document.querySelectorAll("#test").show().hide(); 
	// document.querySelectorAll("#test").show(); 
	// document.querySelectorAll("#test").hide(); 
}());

Q9. The below JavaScript is used to handle mousemove events amongst 3 divs which are nested inside each other. Find and fix the problem which is causing too many events to get fired.

<div id="box1">
	Box 1
	<div id="box2">
		Box2
		<div id="box3">Box3</div>
	</div>
</div>
<script>
	(function() {
		var boxes = [
			document.getElementById("box1"), 
			document.getElementById("box2"), 
			document.getElementById("box3")
		];
		console.log(boxes);
		boxes[0].addEventListener("mousemove", function(event) {
			console.log("Box 1"); 
		});
		boxes[1].addEventListener("mousemove", function(event) {
			console.log("Box 2"); 
		});
		boxes[2].addEventListener("mousemove", function(event) {
			console.log("Box 3"); 
		});
	})();
</script>

Solution: [HTML]

(function() {
	var boxes = [
		document.getElementById("box1"), 
		document.getElementById("box2"), 
		document.getElementById("box3")
	];
	
	boxes[0].addEventListener("mousemove", function(event) {
		console.log("Box 1"); 
		// fix that call ancestor elements' event
		event.stopPropagation(); 
	});
	boxes[1].addEventListener("mousemove", function(event) {
		console.log("Box 2");
		// fix that call ancestor elements' event 
		event.stopPropagation(); 
	});
	boxes[2].addEventListener("mousemove", function(event) {
		console.log("Box 3"); 
		// fix that call ancestor elements' event
		event.stopPropagation(); 
	});
})();