1. var and Hoisting

Question: What will be logged to the console?

JavaScript

console.log(a);
var a = 5;
console.log(a);

Answer:

undefined
5

Explanation:

JavaScript’s hoisting mechanism moves var declarations (but not the assignments) to the top of the scope. The code is executed as if it were:

JavaScript

var a; // Declaration is hoisted and initialized to undefined
console.log(a); // logs undefined
a = 5; // Assignment happens here
console.log(a); // logs 5

2. let/const and the Temporal Dead Zone (TDZ)

Question: What will be logged to the console?

JavaScript

console.log(b);
let b = 10;

Answer:

ReferenceError: Cannot access 'b' before initialization

Explanation:

While let and const are also hoisted, they are not initialized. They are placed in the Temporal Dead Zone (TDZ) from the start of the scope until their declaration is encountered. Trying to access a variable in the TDZ results in a ReferenceError.

3. Closure in a Loop (The Classic Mistake)

Question: What will the following code output?

JavaScript

for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i);
  }, 100);
}

Answer:

3
3
3

Explanation:

The setTimeout callback function creates a closure over the variable i. Since var is function-scoped (or globally scoped in this case) and not block-scoped, there is only one instance of i. By the time the setTimeout callbacks execute (after the loop finishes), the value of i has already been incremented to $3$.

4. Correcting Closure in a Loop

Question: How can you modify the previous code to log $0, 1, 2$?

Answer (using let):

JavaScript

for (let i = 0; i < 3; i++) { // Changed var to let
  setTimeout(function() {
    console.log(i);
  }, 100);
}

Explanation:

Changing var to let makes i block-scoped. In every iteration of the loop, a new variable i is created for that block. The closure captures the correct, per-iteration value.

5. Type Coercion with +

Question: What is the result of this expression?

JavaScript

console.log(1 + "2" + "2");

Answer:

"122"

Explanation:

The + operator performs addition or string concatenation, evaluated from left to right.

  1. 1 + "2": Since one operand is a string, the number 1 is coerced into the string "1". Result: "12".
  2. "12" + "2": Both are strings, so it’s concatenation. Result: "122".

6. Type Coercion with Unary Plus

Question: What is the result of this expression?

JavaScript

console.log(1 + +"2" + "2");

Answer:

"32"

Explanation:

  1. The unary plus operator (+) before "2" attempts to convert its operand to a number. "2" becomes the number $2$. The expression is now 1 + 2 + "2".
  2. 1 + 2: This is standard numeric addition. Result: $3$.
  3. 3 + "2": One operand is a string, so the number $3$ is coerced to "3". Result: "32".

7. Comparing null and 0

Question: What will be the output of the following comparisons?

JavaScript

console.log(null == 0);
console.log(null > 0);
console.log(null >= 0);

Answer:

false
false
true

Explanation:

  1. null == 0: null only equals null or undefined (using ==). It is not equal to $0$ via loose equality.
  2. null > 0: When relational operators (<, >, <=, >=) are used, null is coerced to the number $0$. So, 0 > 0 is false.
  3. null >= 0: null is coerced to $0$. So, 0 >= 0 is true.

8. The delete Operator

Question: What is logged, and why?

JavaScript

var x = 10;
delete x;
console.log(x);

const obj = { y: 20 };
delete obj.y;
console.log(obj.y);

Answer:

10
undefined

Explanation:

  1. delete x: The delete operator is intended to remove a property from an object. It cannot delete variables declared with var, let, or const (even if declared globally with var).
  2. delete obj.y: This does successfully remove the property y from the object obj. Accessing a non-existent property on an object results in undefined.

9. Object Keys and Coercion

Question: What is logged?

JavaScript

const myObject = {};
const a = { key: 'a' };
const b = { key: 'b' };

myObject[a] = 123;
myObject[b] = 456;

console.log(myObject[a]);

Answer:

456

Explanation:

Object keys must be strings or Symbols. When an object is used as a key, it is coerced into a string by calling its toString() method. For plain objects, this returns "[object Object]".

  1. myObject[a] = 123; $\implies$ myObject["[object Object]"] = 123;
  2. myObject[b] = 456; $\implies$ myObject["[object Object]"] = 456; (This overwrites the previous value.)
  3. console.log(myObject[a]); $\implies$ console.log(myObject["[object Object]"]); which is $456$.

10. Automatic Semicolon Insertion (ASI)

Question: What will be logged?

JavaScript

function getGreeting() {
  return
  {
    message: "Hello"
  };
}
console.log(getGreeting());

Answer:

undefined

Explanation:

JavaScript automatically inserts a semicolon after return because of the newline. The code is treated as:

JavaScript

function getGreeting() {
  return; // ASI inserts a semicolon here
  {
    message: "Hello"
  }; // Dead code
}

The function executes return; without a value, returning undefined.

11. this in a Simple Function Call (Non-strict mode)

Question: What is logged (assuming browser environment, non-strict mode)?

JavaScript

var c = 20;
function logC() {
  var c = 10;
  console.log(this.c);
}
logC();

Answer:

20

Explanation:

In a traditional function call (not a method, constructor, or bound function), this defaults to the global object (window in a browser). Since the global var c = 20 creates a property on the global object, this.c resolves to the global variable c, which is $20$. The local var c = 10 is ignored.

12. this in an Arrow Function

Question: What is logged?

JavaScript

var d = 50;
const obj = {
  d: 100,
  getD: () => {
    console.log(this.d);
  }
};
obj.getD();

Answer:

50 (assuming browser/global environment)

Explanation:

Arrow functions do not have their own this context. They capture the this value of the enclosing scope. In this case, the enclosing scope is the global scope, where this refers to the global object, and var d = 50 created a property on it.

13. Double and Triple Equals (== vs ===)

Question: Which of these three comparisons are true?

JavaScript

console.log([] == 0);
console.log(![] == 0);
console.log([] === 0);

Answer:

true
true
false

Explanation:

  1. [] == 0: The empty array is coerced to a primitive, first to an empty string "" (via toString()), and then the empty string is coerced to the number $0$. 0 == 0 is true.
  2. ![] == 0: The logical NOT operator (!) forces the array to a boolean. An array is a truthy value, so ![] is false. false is coerced to $0$. 0 == 0 is true.
  3. [] === 0: The strict equality operator (===) performs no type coercion. An array is not the same type as a number. false.

14. Array length Property

Question: What will be logged?

JavaScript

const arr = [1, 2, 3];
arr[10] = 100;
console.log(arr.length);

Answer:

11

Explanation:

An array’s length property is $1$ more than the highest index. Since the highest index used is $10$, the length is $11$. The elements at indices $3$ through $9$ are present in the array but hold the value undefined.

15. The infamous typeof null

Question: What will be logged?

JavaScript

console.log(typeof null);

Answer:

"object"

Explanation:

This is a long-standing bug in JavaScript that was never fixed for backward compatibility reasons. null represents the intentional absence of any object value, but typeof reports it as "object".

16. parseInt with Radix

Question: What will be logged?

JavaScript

console.log(parseInt('10.00'));
console.log(parseInt('10xyz'));
console.log(parseInt('010'));
console.log(parseInt('010', 8));

Answer:

10
10
10
8

Explanation:

  1. parseInt only parses the integer part.
  2. It stops parsing when it encounters a non-numeric character.
  3. '010' is often treated as base $10$ in modern JS, but historically it sometimes defaulted to octal (base $8$), which is why the second example is tricky. Always specify the radix!
  4. parseInt('010', 8): The string '010' is explicitly parsed in base $8$ (octal). $(0 \cdot 8^2) + (1 \cdot 8^1) + (0 \cdot 8^0) = 8$.

17. The IIFE Return Value

Question: What will be the value of result?

JavaScript

const result = (function(x) {
  delete x;
  return x;
})(10);

console.log(result);<br>

Answer:

10

Explanation:

The function parameter x is a local variable holding the value $10$. As seen in Q8, the delete operator cannot delete a variable declared with var, let, or const, or a function parameter. Therefore, the value of x remains $10$.

18. Promises and Event Loop Order

Question: What will be the order of logs?

JavaScript

console.log(1);

setTimeout(() => console.log(2), 0);

Promise.resolve().then(() => console.log(3));

console.log(4);

Answer:

1
4
3
2

Explanation:

  1. 1 and 4 are logged immediately as they are on the Call Stack.
  2. The Promise.resolve().then() callback is placed in the Microtask Queue (a high-priority queue).
  3. The setTimeout callback is placed in the Macrotask Queue (or Task Queue, lower priority).
  4. The Event Loop checks the Microtask Queue first, logs 3.
  5. Then, it checks the Macrotask Queue, logs 2.

19. Destructuring with undefined

Question: What will be the value of a and b?

JavaScript

const { a, b = 2 } = { a: 1 };
console.log(a, b);

const { c, d = 4 } = { c: 3, d: undefined };
console.log(c, d);

Answer:

1 2
3 4

Explanation:

  1. In the first case, a is $1$ and b is missing, so it takes its default value of $2$.
  2. In the second case, c is $3$. The default value for d (which is $4$) is only used if the property is missing or if the property’s value is explicitly undefined. Since { c: 3, d: undefined } has the property d with the value undefined, the default value of $4$ is assigned.

20. Function Name in Strict Mode

Question: What is the value of foo.name?

JavaScript

const foo = function() {};
const bar = function baz() {};

console.log(foo.name);
console.log(bar.name);

Answer:

foo
baz

Explanation:

In modern JavaScript (ES6+), functions have a readable name property.

  1. For a function expression assigned to a variable, the name defaults to the variable name (foo).
  2. For a named function expression, the name is the internal name (baz). This internal name is primarily for debugging and recursion and is available via the name property.

Questions 21 – 30 (Quick-Fire)

21. Adding properties to a String primitive

JavaScript

let str = 'hello';
str.newProp = 'world';
console.log(str.newProp);
  • Answer: undefined
  • Explanation: String primitives are not objects. Although JavaScript temporarily wraps them in a String object to allow property assignment, this temporary object is discarded immediately, and the property is lost.

22. NaN comparison

JavaScript

console.log(NaN === NaN);
  • Answer: false
  • Explanation: NaN (Not a Number) is a special value that is not equal to anything, including itself. Use Number.isNaN() or isNaN() to check for it.

23. Spread syntax with undefined

JavaScript

const arr = [1, ...[undefined], 3];
console.log(arr.length);
  • Answer: 3
  • Explanation: The spread syntax simply copies the elements. The resulting array is [1, undefined, 3].

24. Mutability and const

JavaScript

const x = { a: 1 };
x.a = 2;
console.log(x.a);
  • Answer: 2
  • Explanation: const prevents re-assignment of the variable identifier (x). It does not prevent mutation of the object or array that the variable references.

25. Labelled Statements

JavaScript

outer: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (i * j === 4) {
      break outer;
    }
    console.log(`i: ${i}, j: ${j}`);
  }
}
  • Answer (Logs only):
    • i: 0, j: 0
    • i: 0, j: 1
    • i: 0, j: 2
    • i: 1, j: 0
    • i: 1, j: 1
    • i: 1, j: 2
    • i: 2, j: 0
    • i: 2, j: 1
  • Explanation: Labelled statements allow break and continue to jump out of or skip specific loops. When $i=2$ and $j=2$, the condition $i \cdot j = 4$ is met, and break outer terminates the entire outer loop, not just the inner one.

26. Array.isArray vs instanceof Array

JavaScript

console.log([] instanceof Array);
console.log(Array.isArray([]));
  • Answer:true true
  • Explanation: They seem equivalent here, but Array.isArray() is more reliable, especially in a multi-frame environment or when dealing with prototypal inheritance, as instanceof can fail if the prototype chain is manipulated or if objects cross realm boundaries.

27. Using a comma operator

JavaScript

let z = (1 + 2, 3 + 4, 5 + 6);
console.log(z);
  • Answer: 11
  • Explanation: The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand. $(5 + 6) = 11$.

28. Implicit type coercion in a while loop

JavaScript

let k = 1;
while (k) {
  console.log(k);
  k--;
}
  • Answer (Logs):1
  • Explanation:
    1. The loop condition k is $1$ (truthy), so it logs $1$.
    2. $k$ becomes $0$.
    3. The loop condition k is $0$ (falsy), so the loop terminates.

29. Spread vs. Object.assign vs. Deep Copy

JavaScript

const original = { value: 1, nested: { deep: 'a' } };
const shallowCopy = { ...original };
shallowCopy.nested.deep = 'b';
console.log(original.nested.deep);
  • Answer: 'b'
  • Explanation: The spread syntax (...) performs a shallow copy. While value is copied, the nested property copies the reference to the original nested object. Changing the nested object in shallowCopy also changes it in original.

30. Function Scope and Re-declaration with var

JavaScript

function getValue() {
  return 10;
}
var getValue = 5;

console.log(typeof getValue);
  • Answer: 'number'
  • Explanation: In JavaScript, a var declaration can overwrite a function declaration with the same name (and vice-versa, depending on the order and complexity). Here, the function declaration is hoisted and created, but the var getValue = 5 assignment executes and overwrites the function reference with the number $5$.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *