JavaScript Interview Questions
typeof bar === "object"
to determine if bar is an object? How can this pitfall be avoided?
#scope
#type
#variable
#null
#undefined
null
is object
(bar !== null) && (typeof bar === "object")
(function(){
var a = b = 3;
})();
console.log("a defined? " + (typeof a !== 'undefined'));
console.log("b defined? " + (typeof b !== 'undefined'));
#function_invocation
#variable
#scope
#use_strict
b
be defined outside of the scope of the enclosing function, try "use strict";
to reveal error.
a defined? false
b defined? true
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
};
myObject.func();
#closure
#scope
#this
#self
#function_invocation
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
#closure
#scope
#this
#self
#function_invocation
// pass jQuery in as $
(function($) { /* $ can be use */ } )(jQuery);
or with ready #noConflict
// release $ from other
$.noConflict();
// wait for document reay and accept argument as $ and use it
jQuery(document).ready(function($){/* $ can be use */});
#use_strict
#global_variable
- Makes debugging easier : Code errors that would otherwise have been ignored or would have failed silently will now generate errors or throw exceptions, alerting you sooner to problems in your code and directing you more quickly to their source.
- Prevents accidental globals : Without strict mode, assigning a value to an undeclared variable automatically creates a global variable with that name. This is one of the most common errors in JavaScript. In strict mode, attempting to do so throws an error.
- Eliminates
this
coercion : Without strict mode, a reference to a this value of null or undefined is automatically coerced to the global. This can cause many headfakes and pull-out-your-hair kind of bugs. In strict mode, referencing athis
value of null or undefined throws an error. - Disallows duplicate property names or parameter values : Strict mode throws an error when it detects a duplicate named property in an object (e.g.,
var object = {foo: "bar", foo: "baz"};
) or a duplicate named argument for a function (e.g.,function foo(val1, val2, val1){}
), thereby catching what is almost certainly a bug in your code that you might otherwise have wasted lots of time tracking down. - Makes eval() safer : There are some differences in the way
eval()
behaves in strict mode and in non-strict mode. Most significantly, in strict mode, variables and functions declared inside of an eval() statement are not created in the containing scope (they are created in the containing scope in non-strict mode, which can also be a common source of problems). - Throws error on invalid usage of delete : The
delete
operator (used to remove properties from objects) cannot be used on non-configurable properties of the object. Non-strict code will fail silently when an attempt is made to delete a non-configurable property, whereas strict mode will throw an error in such a case.
function foo1()
{
return {
bar: "hello"
};
}
function foo2()
{
return
{
bar: "hello"
};
}
console.log("foo1 : " + foo1());
console.log("foo2 : " + foo2());
#pitfall
π‘ It'll see asreturn;
because;
are optional.
foo1 :[object Object]
foo2 : undefined
NaN
? What is its type? How can you reliably test if a value is equal to NaN
?
#pitfall
#Number
#NaN
Not a Number
but beware typeof NaN === "number"
is true
//
isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: "37" is converted to the number 37 which is not NaN
isNaN("37.37"); // false: "37.37" is converted to the number 37.37 which is not NaN
isNaN(""); // false: the empty string is converted to 0 which is not NaN
isNaN(" "); // false: a string with spaces is converted to 0 which is not NaN
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
// This is a false positive and the reason why isNaN is not entirely reliable
isNaN("blabla") // true: "blabla" is converted to a number.
// extra point for ES6
Number.isNaN(NaN);
console.log(0.1 + 0.2);
console.log(0.1 + 0.2 == 0.3);
#pitfall
#Number
Not a Number
but beware typeof NaN === "number"
is true
0.30000000000000004
false
#pitfall
#Number
#Integer
Number.isInteger()
function isInteger(x) { return Math.round(x) === x; }
(function() {
console.log(1);
setTimeout(function(){console.log(2)}, 1000);
setTimeout(function(){console.log(3)}, 0);
console.log(4);
})();
#pitfall
#async
1
4
3
2
#algorithm
function isPalindrome(str) {
// trim non word and make it lower case
str = str.replace(/\W/g, '').toLowerCase();
// compare with reversed text
return (str == str.split('').reverse().join(''));
}
console.log(isPalindrome("level")); // logs 'true'
console.log(isPalindrome("levels")); // logs 'false'
console.log(isPalindrome("A car, a man, a maraca")); // logs 'true'
sum
method which will work properly when invoked using either syntax below.
console.log(sum(2,3)); // Outputs 5
console.log(sum(2)(3)); // Outputs 5
#algorithm
#arguments
#functional
function sum(x) {
if (arguments.length == 2) {
return arguments[0] + arguments[1];
} else {
return function(y) { return x + y; };
}
}
or
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
btn.addEventListener('click', function(){ console.log(i); });
document.body.appendChild(btn);
}
(a) What gets logged to the console when the user clicks on βButton 4β and why? (b) Provide one or more alternate implementations that will work as expected.
#closure
#scope
i
is 5
forever, need input i to closure function.
...
(function (i) {
btn.addEventListener('click', function() { console.log(i); });
})(i);
...
var arr1 = "john".split('');
var arr2 = arr1.reverse();
var arr3 = "jones".split('');
arr2.push(arr3);
console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));
console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));
#array
#referrence
silce(-1)
will pick 1 item backward which is arr3
var arr1 = "john".split(''); // arr1 = ["j","o","h","n"]
var arr2 = arr1.reverse(); // arr2 = arr1 = ["n","h","o","j"]
var arr3 = "jones".split(''); // arr3 = ["j","o","n","e","s"]
arr2.push(arr3); // arr2 = arr1 = ["n","h","o","j",[,"j","o","n","e","s"]]
output
array 1: length=5 last=j,o,n,e,s
array 2: length=5 last=j,o,n,e,s
console.log(1 + "2" + "2");
console.log(1 + +"2" + "2");
console.log(1 + -"1" + "2");
console.log(+"1" + "1" + "2");
console.log( "A" - "B" + "2");
console.log( "A" - "B" + 2);
#String
#Number``#operation
1 + "2" = "12"
and -"1" = -1
also last one will judge type
122
32
02
112
NaN2
NaN
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
nextListItem();
}
};
#recursive
#async
setTimeout
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
setTimeout( nextListItem, 0);
}
};
#recursive
#async
var x = 1;
(function(y) {
var i = "i";
console.log("i:" + i);
console.log("x:" + x);
console.log("y:" + y);
(function(z) {
var j = "j";
console.log("i:" + i);
console.log("j:" + j);
console.log("x:" + x);
console.log("y:" + y);
console.log("z:" + z);
})(3);
})(2);
for (var i = 0; i < 5; i++) {
setTimeout(function() { console.log(i); }, i * 1000 );
}
Explain your answer. How could the use of closures help here?
#closure
#async
5
is print, Need closure to cover setTimeout
for (var i = 0; i < 5; i++) {
(function(i){
setTimeout(function() { console.log(i); }, i * 1000 );
})(i);
}
console.log("0 || 1 = "+(0 || 1));
console.log("1 || 2 = "+(1 || 2));
console.log("0 && 1 = "+(0 && 1));
console.log("1 && 2 = "+(1 && 2));
#logic
0 || 1 = 1 // 1 is true
1 || 2 = 1 // 1 is true
0 && 1 = 0 // 0 is false
1 && 2 = 2 // 1 is true then skip and check 2 which return 2
console.log(false == '0')
console.log(false === '0')
#equal
==
is compare value
, ===
is compare both key
and value
true
false
var a={},
b={key:'b'},
c={key:'c'};
a[b]=123;
a[c]=456;
console.log(a[b]);
#object
b
and c
get convert to [object Object]
a[b]=123; // a["[object Object]"]=123;
a[c]=456; // a["[object Object]"]=456;
so output is
456
console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10));
#closure
f(1): returns n, which is 1
f(2): returns 2 * f(1), which is 2
f(3): returns 3 * f(2), which is 6
f(4): returns 4 * f(3), which is 24
f(5): returns 5 * f(4), which is 120
f(6): returns 6 * f(5), which is 720
f(7): returns 7 * f(6), which is 5040
f(8): returns 8 * f(7), which is 40320
f(9): returns 9 * f(8), which is 362880
f(10): returns 10 * f(9), which is 3628800
(function(x) {
return (function(y) {
console.log(x);
})(2)
})(1);
#closure
1
var hero = {
_name: 'John Doe',
getSecretIdentity: function (){
return this._name;
}
};
var stoleSecretIdentity = hero.getSecretIdentity;
console.log(stoleSecretIdentity());
console.log(hero.getSecretIdentity());
What is the issue with this code and how can it be fixed.
#closure
#function
#call
#bind
function
will miss their scope.
output
undefined
John Doe
Use bind
to fix.
...
var stoleSecretIdentity = hero.getSecretIdentity.bind(hero);
...
Or temporary fix by call
or apply
each function with scope.
...
console.log(stoleSecretIdentity.call(hero));
console.log(stoleSecretIdentity.apply(hero));
...
The arguments to the function should be:
- a DOM element
- a callback function (that takes a DOM element as its argument)
#DOM
#callback
#traverse
function Traverse(p_element, p_callback) {
p_callback(p_element);
var list = p_element.children;
for (var i = 0; i < list.length; i++) {
Traverse(list[i],p_callback); // recursive call
}
}
console.log('hello'.repeatify(3)); // Should print hellohellohello.
#method
#inherit
#prototype
repeatify
from String.prototype
String.prototype.repeatify = String.prototype.repeatify || function(times) {
var str = '';
for (var i = 0; i < times; i++) {
str += this;
}
return str;
};
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();
#scope
undefined
and 2
because what actually happen is
function test() {
var a; // undefined
function foo() {
return 2;
}
console.log(a);
console.log(foo());
a = 1;
}
test();
#overview
#overview
<head></head>
and <body></body>
<head><script type="text/javascript" src="foo.js"></script>/head>
<body><script type="text/javascript">alert(foo);</script></body>
#overview
// one line
/*
multi line
multi line
*/
#overview
#variable
// local
var _local = "foo";
global = "bar";
#type
#undefined
#null
var foo
this
keyword in JavaScript.
#overview
#this
this
used to reference the object in which the function is operating.
#overview
#overview
#event
window.onload
and the jQuery $(document).ready()
method?
#overview
#event
- The
window.onload method
occurs after all the page elements have loaded(HTML, CSS, images), which can result in a delay. - The
$(document).ready()
method begins to run code as soon as the Document Object Model (DOM) is loaded, which should be faster and less prone to loading errors across different browsers.
['1', '2', '3'].map(parseFloat);
//=> [1, 2, 3]
['1', '2', '3'].map(parseInt);
//=> [ 1, NaN, NaN ]
#functional
['1', '2', '3'].map(function (str) {
return parseInt(str);
});
var text = 'outside';
function logIt(){
console.log(text);
var text = 'inside';
};
logIt();
#scope
undefined
because what actually happen is
var text = 'outside';
function logIt(){
var text; // undefined
console.log(text);
text = 'inside';
};
logIt();
References
- http://bahmutov.calepin.co/functional-javascript-interview-question.html
- http://www.skilledup.com/articles/20-must-know-javascript-interview-qa
- https://www.interviewcake.com/javascript-interview-questions
- https://blog.udemy.com/javascript-interview-questions/
- http://www.toptal.com/javascript/interview-questions
- https://github.com/diegocard/js-questions/blob/master/questions%2FjQuery.md
- http://www.sitepoint.com/5-typical-javascript-interview-exercises/
- http://www.w3schools.com/js/js_quiz.asp