JavaScript, while flexible and powerful, has its fair share of nuances that can trip even seasoned developers. Let’s dive into some of these tricky areas.
Type Coercion & Comparisons
- Question: What is the result of ‘5’ + 3? Answer: ’53’. JavaScript coerces the number 3 to a string and concatenates it with ‘5’.
- Question: What is the result of ‘5’ – 3? Answer: 2. JavaScript coerces the string ‘5’ to a number before performing the subtraction.
- Question: What is the result of 1 + ‘2’ + 3? Answer: ‘123’. The first + coerces 1 to a string, and then the subsequent + performs string concatenation.
- Question: What is the result of 3 + ‘2’ – 1? Answer: 31. 3 + ‘2’ becomes ’32’, and then ’32’ – 1 coerces ’32’ to a number, resulting in 31.
- Question: What is the result of [] == false? Answer: true. The empty array [] is coerced to 0 when compared to a number, and false is also coerced to 0.
- Question: What is the result of [] == ![]? Answer: true. ![] evaluates to false. As seen above, [] == false is true.
- Question: What is the result of {} == false? Answer: false. The object {} is coerced to NaN when compared numerically, and NaN == 0 is false.
- Question: What is the result of null == undefined? Answer: true. This is a special case in JavaScript’s loose equality.
- Question: What is the result of null === undefined? Answer: false. The strict equality operator (===) checks both value and type without coercion, and null and undefined are different types.
- Question: What is the result of NaN == NaN? Answer: false. NaN is not equal to itself.
Scope & Closures
-
Question: What will the following code output?
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 100); }
Answer:
5
will be logged five times. Becausevar
has function scope (or global scope outside a function), the loop completes, and the value ofi
is5
before any of thesetTimeout
callbacks execute. - Question: How can you modify the previous code to log 0, 1, 2, 3, 4?Answer: Use let instead of var, or create a closure within the loop:
// Using let for (let i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 100); } // Using a closure for (var i = 0; i < 5; i++) { (function(j) { setTimeout(function() { console.log(j); }, j * 100); })(i); }
-
Question: What will the following code output?
var a = 10; function foo() { console.log(a); var a = 20; } foo();
Answer:
undefined
. Due to hoisting, thevar a = 20;
insidefoo
is moved to the top of the function scope. So,console.log(a)
is executed beforea
is actually assigned the value20
. - Question: What is a closure in JavaScript?
Answer: A closure is a function bundled together with its surrounding state (lexical environment). This means a closure can remember and access variables from its outer function’s scope even after the outer function has finished executing.
15. Question: What will the following code output?
function outer() {
var count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
var increment = outer();
increment();
increment();
Answer: 1
then 2
. The inner
function forms a closure over the count
variable in the outer
function’s scope. Each call to increment
(which refers to the inner
function) increments and logs the same count
variable.
this
Keyword
- Question: What does the this keyword refer to in a regular function call?Answer: In non-strict mode, this refers to the global object (window in browsers, global in Node.js). In strict mode (‘use strict’), this is undefined.
- Question: What does the this keyword refer to inside a method of an object?Answer: It refers to the object that the method is called on.
- Question: How does this behave inside an arrow function?Answer: Arrow functions do not have their own this binding. They lexically inherit the this value from their surrounding scope.
- Question: How can you explicitly set the value of this for a function call?Answer: Using the call(), apply(), or bind() methods.
-
Question: What will the following code output?
const obj = { name: 'Alice', greet: function() { setTimeout(function() { console.log('Hello, ' + this.name); }, 100); } }; obj.greet();
Answer:
'Hello, undefined'
(in non-strict mode in a browser). Inside thesetTimeout
callback,this
refers to the globalwindow
object, which doesn’t have aname
property. - Question: How can you fix the this issue in the previous question?Answer: Several ways:
- Using an arrow function in
setTimeout
:const obj = { name: 'Alice', greet: function() { setTimeout(() => { console.log('Hello, ' + this.name); }, 100); } };
- Using
bind(this)
:const obj = { name: 'Alice', greet: function() { setTimeout(function() { console.log('Hello, ' + this.name); }.bind(this), 100); } };
- Storing
this
in a variable:const obj = { name: 'Alice', greet: function() { const self = this; setTimeout(function() { console.log('Hello, ' + self.name); }, 100); } };
- Using an arrow function in
Promises & Async/Await
- Question: What is the state of a Promise when it’s first created? Answer: pending.
- Question: What are the possible states of a settled Promise? Answer: fulfilled (or resolved) and rejected.
- Question: What is the purpose of the then() method of a Promise? Answer: It’s used to handle the fulfillment of a Promise, receiving the resolved value. It can also return another Promise, creating a Promise chain.
- Question: What is the purpose of the catch() method of a Promise? Answer: It’s used to handle the rejection of a Promise, receiving the error reason.
- Question: What is the purpose of the finally() method of a Promise? Answer: It allows you to execute code regardless of whether the Promise was fulfilled or rejected. It doesn’t receive the final value or error.
- Question: What does the async keyword do? Answer: It makes a function return a Promise. If the function explicitly returns a non-Promise value, it will be wrapped in a resolved Promise.
- Question: What does the await keyword do? Answer: It can only be used inside an async function. It pauses the execution of the async function until the Promise it precedes settles (either resolves or rejects).
- Question: How do you handle errors within an async/await function?Answer: Using a try…catch block.
-
Question: What will the following code output?
async function example() { console.log('Start'); await new Promise(resolve => setTimeout(resolve, 100)); console.log('End'); } example(); console.log('Middle');
Answer:
Start Middle End
The
await
pauses theexample
function, but the synchronousconsole.log('Middle')
runs immediately.
Object Properties & Prototypes
- Question: What is the difference between obj.property and obj[‘property’]?Answer: Both are used to access object properties. However, obj[‘property’] allows you to use variable property names or property names that are not valid JavaScript identifiers (e.g., containing spaces).
- Question: What is the purpose of the Object.keys() method? Answer: It returns an array of a given object’s own enumerable property names, in the order they are iterated over in a loop.
- Question: What is the prototype chain in JavaScript? Answer: It’s a mechanism for object inheritance. When you try to access a property of an object, JavaScript first looks at the object itself. If the property1 is not found, it searches the object’s prototype, then the prototype’s prototype, and so on, until it finds the property or reaches the2 end of the chain (null).
- Question: How can you set the prototype of an object? Answer: Using Object.setPrototypeOf(obj, prototype) or by using Object.create(prototype) when creating the object.
- Question: What is the difference between hasOwnProperty() and in operator? Answer: hasOwnProperty() returns true if the object has the specified property as a direct property (not inherited through the prototype chain). The in operator returns true if the specified property is in the object or its prototype chain.
-
Question: What will the following code output?
function Foo() { this.value = 42; } Foo.prototype.value = 99; const bar = new Foo(); console.log(bar.value);
Answer:
42
. Whennew Foo()
is called, theFoo
constructor is executed, andthis.value = 42
sets thevalue
property directly on thebar
object, overriding the prototype property.
Arrays
- Question: What is the result of [1, 2, 3] + [4, 5, 6]? Answer: ‘1,2,34,5,6’. JavaScript converts the arrays to strings using their toString() method and then concatenates them.
- Question: What is the difference between slice() and splice() array methods? Answer:
slice()
returns a new array containing a portion of the original array. It does not modify the original array.splice()
changes the contents of an array by removing or replacing existing elements and/or3 adding new elements in place. It returns an array4 containing the deleted elements.
39. Question: How do you empty an array in JavaScript? List at least three ways.
Answer:
-
arr.length = 0;
arr.splice(0, arr.length);
arr = [];
(This creates a new empty array and reassigns the variable, but doesn’t affect other references to the original array).
40 . Question: What will the following code output?
const arr = [1, 2, 3];
arr[10] = 5;
console.log(arr.length);
Answer: 11
. JavaScript allows you to set elements at arbitrary indices, and the length
property is updated to reflect the highest index plus one. The elements at indices 3 through 9 will be undefined
.
Tricky Bits & Edge Cases
- Question: What is the result of 0.1 + 0.2 == 0.3? Answer: false. Due to floating-point precision issues, 0.1 + 0.2 results in a value slightly different from 0.3.
- Question: What is the output of typeof NaN? Answer: ‘number’. This is a well-known quirk of JavaScript.
- Question: What is the output of typeof null? Answer: ‘object’. This is another historical quirk in JavaScript.
- Question: What is the difference between map() and forEach() array methods?Answer:
map()
creates a new array by calling a provided function on every element in the calling array.forEach()
executes a provided5 function once for each array element but does not create a new array. It returnsundefined
.
45. Question: What is the purpose of the use strict directive?
Answer: It enables “strict mode” in JavaScript, which enforces stricter parsing and error handling on your code. It helps to catch common coding mistakes and “unsafe” actions.
46. Question: What are the falsy values in JavaScript?
Answer: false, null, undefined, 0, NaN, and ” (empty string). All other values are truthy.
47. Question: What is the difference between let, const, and var?
Answer:
-
var
has function scope (or global scope outside a function) and is hoisted.let
has block scope and is hoisted but not initialized (you can’t use it before its declaration). It can be reassigned.const
has block scope and is hoisted but not initialized. It cannot be reassigned after its initial assignment.
48. Question: What will the following code output?
console.log(1 < 2 < 3);
console.log(3 > 2 > 1);
Answer:
true
false
For 1 < 2 < 3, it evaluates as (1 < 2) < 3, which is true < 3. true is coerced to 1, so 1 < 3 is true.
For 3 > 2 > 1, it evaluates as (3 > 2) > 1, which is true > 1. true is coerced to 1, so 1 > 1 is false.
49. Question: What is event bubbling and event capturing in the DOM?
Answer:
-
- Event Bubbling: The event propagates upwards through the DOM tree, from the target element to its parent, and so on, up to the document.
- Event Capturing: The event propagates downwards through the DOM tree, starting from the window, then the document, and down to the target element. Event listeners are triggered in this order.
50. Question: What is the output of the following code?
function sayHi() {
console.log(name);
console.log(age);
var name = 'Lydia';
let age = 21;
}
sayHi();
Answer:
undefined
ReferenceError: Cannot access 'age' before initialization
name
is declared with var
, so it’s hoisted, but not initialized until the line var name = 'Lydia';
is reached. age
is declared with let
, which is also hoisted but not initialized, leading to a ReferenceError
when you try to access it before its declaration.
Wrapping Up
JavaScript’s intricacies can be both fascinating and frustrating. By understanding these tricky questions and their underlying concepts, you’ll be better equipped to write more robust and predictable code. Keep practicing and exploring, and you’ll master the nuances of this powerful language!