Practice Questions

Use these questions to test your understanding of this chapter.

1. JavaScript is a dynamically typed and weakly typed language (implicit type coercion). With an example, explain these characteristics of JavaScript.

Solution

Dynamically typed means variables are assigned a type at runtime based on their value, not at declaration. You do not specify types like int or string. A variable can hold any type:

let x = 42;  // x is a number
x = "hello";  // now x is a string

Weakly typed (implicit coercion) means JavaScript automatically converts types when operators are applied:

"5" - 2;  // 3 (string coerced to number)
"5" + 2;  // "52" (number coerced to string)
true + 1;  // 2 (boolean coerced to number)

2. JavaScript has two “bottom” values: null and undefined. Provide any two interesting facts that you can recall from this chapter about these.

Solution

Any two of the following:

  • An uninitialized variable is undefined, while null means the value is intentionally absent.
  • You generally should not deliberately set a value to undefined; prefer null to indicate intentional absence.
  • typeof undefined returns "undefined", but typeof null returns "object" (a known JavaScript quirk).
  • “Not defined” (ReferenceError) and undefined are different things. A declared but uninitialized variable is undefined, while using an undeclared variable throws a ReferenceError.

3. What will typeof return for each of the following values?

typeof 42
typeof "hello"
typeof true
typeof undefined
typeof { name: "Ali" }
typeof [1, 2, 3]
Solution
typeof 42              // "number"
typeof "hello"         // "string"
typeof true            // "boolean"
typeof undefined       // "undefined"
typeof { name: "Ali" } // "object"
typeof [1, 2, 3]       // "object"

Note that arrays return "object" because arrays are a type of object in JavaScript. To specifically check if something is an array, use Array.isArray().

4. In modern JavaScript, we can use the variable declaration keywords let and const. If you want to declare an array, will you use let or const? Please justify your decision.

Solution

Use const. The const keyword creates a read-only reference to a value. It prevents reassigning the variable to a different array. However, it does not make the array itself immutable. You can still modify the array’s contents (push, pop, change elements):

const numbers = [1, 2, 3];
numbers.push(4);  // OK: [1, 2, 3, 4]
numbers[0] = 99;  // OK: [99, 2, 3, 4]
numbers = [5, 6, 7];  // Error: Assignment to constant variable

With const, you cannot accidentally reassign the variable, but you can still do normal array operations.

5. Rewrite this code using a template literal:

const name = "Ali";
const age = 25;
const message = "My name is " + name + " and I am " + age + " years old.";
Solution
const name = "Ali";
const age = 25;
const message = `My name is ${name} and I am ${age} years old.`;

6. Write code that takes the string "javaScript" and produces the output "JavaScript" using string methods. Your solution should work for any string where you want to capitalize only the first letter.

Solution
const original = "javaScript";
const result = original.charAt(0).toUpperCase() + original.slice(1);
console.log(result);  // "JavaScript"

Alternative using bracket notation:

const result = original[0].toUpperCase() + original.slice(1);

Note: You cannot simply do original[0] = "J" because strings are immutable in JavaScript.

7. The console object provides several methods including log, warn, and error. When would you choose one over the others? What is the practical benefit of distinguishing between them?

Solution
  • console.log: General information, debugging output, printing variable values.
  • console.warn: Non-critical issues that do not stop execution but should be noted (e.g., deprecated features, unexpected but handled conditions).
  • console.error: Actual errors or failures that need attention.

Practical benefits:

  • Visual distinction: Browsers typically color these differently (black, yellow, red).
  • Filtering: Developer tools allow filtering by log level, making it easier to find errors in noisy output.
  • In Node.js, warn and error write to stderr instead of stdout, allowing proper stream separation.

8. JavaScript represents all numbers as 64-bit floating-point. What implications does this have for developers? Give an example of a situation where this could cause unexpected behavior.

Solution

Implications:

  • There is no distinction between integers and decimals. 3 and 3.0 are the same.
  • Division always produces floating-point results: 1 / 2 gives 0.5, not 0.
  • Floating-point precision errors can occur with decimal arithmetic.

Example of unexpected behavior:

console.log(0.1 + 0.2);  // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3);  // false

This matters in financial calculations, or anywhere you need exact decimal precision.

9. A user enters "42px" into a form field that expects a number. Write code that extracts the numeric value 42 from this string. What would happen if you used Number("42px") instead?

Solution
const input = "42px";
const value = Number.parseInt(input, 10);  // 42
console.log(value);

Number.parseInt parses from the beginning of the string until it hits a non-numeric character. Always provide the radix (10); it avoids edge cases where the base is detected automatically.

If you used Number("42px") instead, it would return NaN because Number() requires the entire string to be a valid number representation.

console.log(Number("42px"));        // NaN
console.log(Number.parseInt("42px"));  // 42

10. Explain why the var keyword is discouraged in modern JavaScript. What problems does let solve that var does not?

Solution

Problems with var:

  • var is function-scoped, not block-scoped. Variables declared in loops or if-blocks leak outside:

    for (var i = 0; i < 3; i++) {}
    console.log(i);  // 3 (still accessible!)
    
  • var allows redeclaration without error, which can hide bugs:

    var name = "Ali";
    var name = "John";  // No error
    
  • var declarations are hoisted, allowing use before declaration (the variable evaluates to undefined instead of throwing an error).

let solves these by being block-scoped, throwing errors on redeclaration, and throwing a ReferenceError if accessed before declaration.

11. A student suggests using BigInt for all numeric calculations to avoid precision issues. Is this a good idea? Explain your reasoning.

Solution

No, this is not a good idea. BigInt handles arbitrarily large integers without precision loss, but it has limitations:

  • BigInt only works with integers. It cannot represent decimals like 3.14.

  • You cannot mix BigInt with regular numbers in operations:

    const big = 10n;
    console.log(big + 1);  // TypeError: Cannot mix BigInt and other types
    
  • Many APIs and libraries expect regular numbers.

  • BigInt has performance overhead for simple calculations.

Use BigInt only when you specifically need integers larger than Number.MAX_SAFE_INTEGER (2^53 - 1).