Being great developer has nothing to do with passing interview, because most interviews are about weird questions, like what are your weaknesses and question about the legacy feature of a language which nobody hasn't used in 10 years. Nevertheless, we have to play the game by the rules.
#0 Tricky Function Call
var result = (function(a) { | |
return a*a; | |
}(5.5)); | |
console.log(result); |
What is the output in the console?
Answer
The answer is 30.25
. The trick is, if you put parentheses with arguments immediately after function declaration, that will be considered a function call.
#1 Fat Arrow + Declaration Overlap
const b = [1, 2, 3]; | |
const f = (a, ...b) => a + b; | |
console.log(f(1)); |
What is the output in the console?
Answer
The answer is '1'
. The trick is that due to duplicate declaration of b as variable and parameter, it gets resolved as parameter. Since we call our function only with 1
parameter – 1 + []
equals '1'
. Pay attention that type of returned value is string.
#2 Variable and Function Names Overlap
let f = (...f) => f; | |
console.log(f(10)); | |
f = (...f) => f.reduce(f => f); | |
console.log(f(10)); | |
function ff() { | |
return arguments; | |
} | |
console.log(ff(10)); | |
f = f => f; | |
console.log(f(10)); |
What is the output in the console?
Answer
Output will be [10], 10, [10], 10
. The key is to understand that in case of variable and parameter names war – parameter wins. There are a few other tricks here. arguments
is an object and in this case it is [10]
. ...f
is a way to group the rest of the function parameters into named array, in this case all the parameters are resulting into [10]
.
#3 Variable Scope
var foo = 10; | |
bar = 3; | |
(function () { | |
var foo = 2; | |
bar = 1; | |
}()) | |
bar = bar + foo; | |
console.log(bar); |
What is the output in the console?
Answer
There are two tricks here. First – executing code using function scope – (function(){}())
pattern. Second – exploiting global/local scope overlap. Both foo
and bar
defined in global scope. Function redefines foo
in local scope, so global foo
is not changed, when bar
gets reassigned to 1
. Finally, 1 + 10 = 11
.
#4 Global + Local
var x = 5; | |
(function () { | |
console.log(x); | |
var x = 10; | |
console.log(x); | |
})(); |
What is the output in the console?
Answer
This will print out undefined
and 10
rather than 5
and 10
since JavaScript always moves variable declarations (not initializations) to the top of the scope, making the code equivalent to:
var x = 5; | |
(function () { | |
var x; | |
console.log(x); | |
x = 10; | |
console.log(x); | |
})(); |
#5 Chained Assignment
(function(){ | |
var a = b = 3; | |
})(); | |
console.log(typeof a); | |
console.log(typeof b); |
What is the output in the console?
Answer
This will print out undefined
and number
rather than number
and number
since var a = b = 3
is equivalent to b = 3; var a = b;
. Making b
global variable. What is usage of chained notation is not recommended by many styles to avoid accidental global variable declarations.
#6 Auto Semicolon
function foo1() { | |
return { | |
bar: 'bar', | |
}; | |
} | |
function foo2() { | |
return | |
{ | |
'bar'; | |
} | |
} | |
console.log(foo1()); | |
console.log(foo2()); |
What is the output in the console?
Answer
This will print out object
and undefined
. Javascript has automatic semicolon insertion and one of them is inserting semicolon after return statement, making second function equal to return;
, thus returning undefined
.
#7 Javascript Number
console.log(0.1 + 0.2); | |
console.log(0.1 + 0.2 === 0.3); | |
console.log(9007199254740993 === 9007199254740992); |
What is the output in the console?
Answer
Most likely it will output 0.30000000000000004
, false
, and true
. Number in JS are represented as double-precision 64-bit binary format IEEE 754 values. Thus there are rounding errors, as well as there is Number.MAX_SAFE_INTEGER
, after which Number.MAX_SAFE_INTEGER === Number.MAX_SAFE_INTEGER + 1
equals to true
. Number.EPSILON should be used to avoid rounding error while comparing numbers in javascript for equality.
#8 Object Keys
const a = {}, | |
b = {c:'b'}, | |
c = {b:'c'}; | |
a[b] = 111; | |
a[c] = 333; | |
console.log(a[b]); |
What is the output in the console?
Answer
This will print out 333
, not 111
. When setting an object property, JavaScript will implicitly stringify the parameter value. In this case, since b
and c
are both objects, they will both be converted to "[object Object]"
. As a result, a[b]
anda[c]
are both equivalent to a["[object Object]"]
and can be used interchangeably. Thus, setting or referencing a[c]
is precisely the same as setting or referencing a[b]
.
#9 setTimeout Loops
for (var i = 0; i < 5; i++) { | |
setTimeout(function() { console.log(i); }, i * 1000 ); | |
} | |
for (let i = 0; i < 5; i++) { | |
setTimeout(function() { console.log(i); }, i * 1000 ); | |
} |
What is the output in the console?
Answer
This will print out 5, 5, 5, 5, 5
and 0, 1, 2, 3, 4
.
setTimeout
function will be called after whole cycle is executed because of JavaScript event queue. Variables declared using var
are global by default – meaning i
would be equal to 5
after the end of a cycle. Since all setTimeout functions are called after the cycle, the all would print 5
.
Output of second loop even more bizarre. In ECMA 6 specification, the specified behaviour is that in for(let i;;){}
i
gets a new binding for every iteration of the loop. Essentially each closure inside a loop gets a different instance of i
#10 Chained Relationals
console.log(1 < 2 < 2); | |
console.log(3 > 2 > 1); |
What is the output in the console?
Answer
This will print out true
and false
. There are two tricks here. In Javascript relational operators evaluated from left to right, false equals 0
, and true equals 1
for number comparisons. First expression after first step is true < 2
=> 1 < 2
=> true
, and second is true > 1
=> 1 > 1
=> false
.
TL; DR;
Javascript has many interview traps, so unless you prepare for them or have memorized ECMA specifications you are likely to fail at an interview at some point.
Comments