πŸŽ“ Velnov

🟨 JavaScript · Topic 4 of 20

Type Coercion & Equality β€” JavaScript Questions with Answers

30 practice questions on Type Coercion & Equality, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.

2 easy Β· 12 medium Β· 16 hard Β· Part of JavaScript: The language of the web - basics to advanced, 20 topics.

Key concepts in this topic

CoercionType conversionStrict equalityBest practicesTruthyFalsyTruthinessObjectsLoose equalityGotchasCoercion rulesnullundefinedNaNNumber.isNaNNumber()Number conversionBoolean coercionArithmeticArray coercionObject coerciontoStringNumeric coercionString comparison

Jump to: Easy Β· Medium Β· Hard

Easy questions (2)

Q1. easy

What is type coercion?

console.log("5" + 3);   // "53" - number coerced to string
console.log("5" - 3);   // 2    - string coerced to number
  1. A JavaScript automatically converting a value from one type to another during an operation
  2. B Forcing a variable to keep one type
  3. C Deleting a type
  4. D A syntax error

Answer: A β€” JavaScript automatically converting a value from one type to another during an operation

When operands have different types, JavaScript silently converts one to match - like turning 5 into "5" for concatenation. Convenient, but the cause of many surprises.

CoercionType conversion

Q2. easy

What is the difference between == and ===?

console.log(5 == "5");    // true
console.log(5 === "5");   // false
  1. A == converts types before comparing (loose); === requires the same type (strict)
  2. B They are identical
  3. C === is slower and deprecated
  4. D == only works with numbers

Answer: A β€” == converts types before comparing (loose); === requires the same type (strict)

5 == "5" is true (the string is converted). 5 === "5" is false (number vs string). Best practice: always use === unless you deliberately want coercion.

Strict equalityBest practices

Medium questions (12)

Q3. medium

Which values are FALSY in JavaScript?

if ("") { }       // skipped
if ("0") { }      // runs! non-empty string
if ([]) { }       // runs! empty array is truthy
  1. A false, 0, -0, "", null, undefined, NaN (and 0n)
  2. B Only false
  3. C false, 0 and []
  4. D Everything except true

Answer: A β€” false, 0, -0, "", null, undefined, NaN (and 0n)

Those are the only falsy values - EVERYTHING else is truthy, including "0", "false", [], {} and negative numbers. Memorising this short list explains most if-statement surprises.

TruthyFalsy

Q7. medium

What is the output? console.log(null == undefined, null === undefined);

if (value == null) { }   // catches null AND undefined
  1. A true false
  2. B true true
  3. C false false
  4. D false true

Answer: A β€” true false

A special rule makes null and undefined loosely equal to each other (and to nothing else). Strictly they are different types. Handy: value == null tests for 'null OR undefined' in one check.

nullundefined

Q9. medium

What does Number("") return?

console.log(Number(""));      // 0
console.log(Number("  "));    // 0
console.log(Number("abc"));   // NaN
  1. A 0 - an empty string converts to zero
  2. B NaN
  3. C undefined
  4. D ""

Answer: A β€” 0 - an empty string converts to zero

Number("") and Number(" ") are both 0, which surprises people expecting NaN. Number("abc") is NaN. This is why empty form fields can silently become 0.

Number()Coercion

Q10. medium

What is the output? console.log(Number(true), Number(false), Number(null));

console.log(Number(undefined));   // NaN
console.log(Number(null));        // 0
  1. A 1 0 0
  2. B true false null
  3. C 1 0 NaN
  4. D NaN NaN NaN

Answer: A β€” 1 0 0

true converts to 1, false to 0, and null to 0. (But Number(undefined) is NaN - another inconsistency between null and undefined.)

Number conversion

Q15. medium

What is the output? console.log("10" > "9");

console.log("10" > "9");           // false - string compare
console.log(10 > 9);                // true
console.log("10" > 9);              // true - mixed types convert to number
  1. A false - two strings compare ALPHABETICALLY, and "1" comes before "9"
  2. B true
  3. C NaN
  4. D SyntaxError

Answer: A β€” false - two strings compare ALPHABETICALLY, and "1" comes before "9"

When both operands are strings, comparison is lexicographic (character by character), not numeric. "10" > "9" is false. Convert first: Number("10") > Number("9") is true.

String comparisonSorting

Q17. medium

What is the safest way to compare two values?

  1. A Use === (and !==) so no hidden conversion happens
  2. B Always use ==
  3. C Use = for comparison
  4. D Convert everything to strings first

Answer: A β€” Use === (and !==) so no hidden conversion happens

=== compares type and value with no surprises. The single accepted exception is x == null to catch both null and undefined at once.

Best practicesStrict equality

Q19. medium

How do you safely convert user input "42" to a number?

const n = Number(input);
if (Number.isNaN(n)) {
  alert("Please enter a number");
}
  1. A Number(input) or parseInt(input, 10) - then check with Number.isNaN()
  2. B input.toNumber()
  3. C (int) input
  4. D input * "1"

Answer: A β€” Number(input) or parseInt(input, 10) - then check with Number.isNaN()

Number() is strict (rejects "42abc"); parseInt(str, 10) reads leading digits. Always pass the radix 10 to parseInt and verify the result is not NaN.

parseIntValidation

Q21. medium

What does String(null) return?

console.log("Value: " + null);   // "Value: null"
  1. A "null" (the text)
  2. B ""
  3. C null
  4. D undefined

Answer: A β€” "null" (the text)

String() turns any value into readable text, including "null" and "undefined". That is why concatenating a null value shows the word null in the UI.

String()Concatenation

Q23. medium

How can you check whether a value is a real number (not NaN, not a numeric string)?

Number.isFinite(42);      // true
Number.isFinite("42");    // false
Number.isFinite(NaN);     // false
  1. A typeof v === "number" && !Number.isNaN(v) (or Number.isFinite(v))
  2. B typeof v === "number" only
  3. C v > 0
  4. D isNaN(v) === false

Answer: A β€” typeof v === "number" && !Number.isNaN(v) (or Number.isFinite(v))

typeof alone accepts NaN (whose type is "number"). Number.isFinite(v) is the neat one-call version - it rejects NaN, Infinity and non-numbers.

Number.isFiniteValidation

Q25. medium

What does JSON.parse() do with the string '{"a":1}'?

const obj = JSON.parse('{"a":1}');
console.log(obj.a);              // 1
console.log(JSON.stringify(obj)); // '{"a":1}'
  1. A Converts JSON TEXT into a real JavaScript object
  2. B Converts an object into text
  3. C Validates the object
  4. D Deletes the object

Answer: A β€” Converts JSON TEXT into a real JavaScript object

JSON.parse turns text into objects (used on API responses); JSON.stringify does the reverse (used before sending or storing data).

JSONAPIs

Q27. medium

Which comparison is safe for checking if a variable exists and has a value?

  1. A if (value != null) - catches both null and undefined
  2. B if (value) - also rejects 0 and ""
  3. C if (value !== false)
  4. D if (typeof value)

Answer: A β€” if (value != null) - catches both null and undefined

if (value) rejects legitimate values like 0 and "". value != null (the one accepted use of loose equality) checks only for null/undefined. Modern alternative: value ?? fallback.

null checksNullish

Q29. medium

What does Object.is(NaN, NaN) return?

console.log(Object.is(NaN, NaN));   // true
console.log(NaN === NaN);            // false
console.log(Object.is(0, -0));       // false
  1. A true - Object.is treats NaN as equal to itself, unlike ===
  2. B false
  3. C NaN
  4. D undefined

Answer: A β€” true - Object.is treats NaN as equal to itself, unlike ===

Object.is is like === with two fixes: NaN equals NaN, and +0 is NOT equal to -0. Useful for precise value comparison.

Object.isNaN

Hard questions (16)

Q4. hard

What is the output? console.log(Boolean([]), Boolean({}));

if (arr.length === 0) { }              // correct emptiness test
if (Object.keys(obj).length === 0) { }
  1. A true true - empty arrays and objects are TRUTHY
  2. B false false
  3. C true false
  4. D false true

Answer: A β€” true true - empty arrays and objects are TRUTHY

Any object - including an empty array or object - is truthy. To test emptiness check arr.length === 0 or Object.keys(obj).length === 0.

  • This trips up people coming from Python, where [] is falsy.

TruthinessObjects

Q5. hard

What is the output? console.log([] == false);

console.log([] == false);    // true  (coerced)
console.log(Boolean([]));    // true  (truthy)
console.log([] === false);   // false (strict)
  1. A true - [] converts to "" then to 0, and false converts to 0
  2. B false
  3. C undefined
  4. D TypeError

Answer: A β€” true - [] converts to "" then to 0, and false converts to 0

Loose equality converts both sides to numbers: [] becomes "" becomes 0, and false becomes 0. So 0 == 0 is true - even though Boolean([]) is true! A perfect argument for using ===.

Loose equalityGotchas

Q6. hard

What is the output? console.log("" == 0, "0" == 0, "" == "0");

  1. A true true false - == converts strings to numbers, but "" and "0" are different strings
  2. B true true true
  3. C false false false
  4. D false true false

Answer: A β€” true true false - == converts strings to numbers, but "" and "0" are different strings

"" converts to 0 (true), "0" converts to 0 (true), but comparing two STRINGS does no numeric conversion, so "" == "0" is false. Loose equality is not transitive - a classic demonstration of why to avoid it.

Loose equalityCoercion rules

Q8. hard

What is the output? console.log(NaN == NaN, NaN === NaN);

  1. A false false - NaN is never equal to anything, including itself
  2. B true true
  3. C true false
  4. D SyntaxError

Answer: A β€” false false - NaN is never equal to anything, including itself

The IEEE floating-point standard defines NaN as unequal to everything. Test with Number.isNaN(x) or Object.is(x, NaN).

NaNNumber.isNaN

Q11. hard

What is the output? console.log(true + true);

  1. A 2 - booleans convert to 1 and 0 in arithmetic
  2. B "truetrue"
  3. C true
  4. D NaN

Answer: A β€” 2 - booleans convert to 1 and 0 in arithmetic

Arithmetic coerces booleans to numbers: true is 1, so 1 + 1 = 2. A neat trick: array.filter(Boolean).length or summing booleans to count matches.

Boolean coercionArithmetic

Q12. hard

What is the output? console.log([] + []);

console.log(typeof ([] + []));   // "string"
console.log([1,2] + [3]);        // "1,23"
  1. A "" (an empty string) - both arrays convert to empty strings and concatenate
  2. B []
  3. C 0
  4. D NaN

Answer: A β€” "" (an empty string) - both arrays convert to empty strings and concatenate

The + operator converts objects to primitives; an array becomes its join(",") string, so [] becomes "". Empty + empty = empty string. The result is a string, not an array.

Array coercionGotchas

Q13. hard

What is the output? console.log([] + {});

  1. A "[object Object]" - [] becomes "" and {} becomes "[object Object]"
  2. B "{}"
  3. C 0
  4. D TypeError

Answer: A β€” "[object Object]" - [] becomes "" and {} becomes "[object Object]"

A plain object's default string form is "[object Object]", so "" + "[object Object]" gives that famous string. Seeing it in your UI means you printed an object instead of its contents - use JSON.stringify() instead.

Object coerciontoString

Q14. hard

What is the output? console.log("5" * "2");

  1. A 10 - both strings are converted to numbers
  2. B "52"
  3. C NaN
  4. D "10"

Answer: A β€” 10 - both strings are converted to numbers

*, -, / and % have only a numeric meaning, so both operands are converted. Only + is ambiguous because it also concatenates.

Numeric coercion

Q16. hard

Why does [10, 9, 100].sort() give [10, 100, 9]?

console.log([10, 9, 100].sort());              // [10, 100, 9]
console.log([10, 9, 100].sort((a,b) => a-b));   // [9, 10, 100]
  1. A sort() converts elements to STRINGS by default and sorts alphabetically
  2. B sort() is broken
  3. C It sorts by length
  4. D It sorts randomly

Answer: A β€” sort() converts elements to STRINGS by default and sorts alphabetically

The default sort compares string forms: "10" < "100" < "9". For numbers you must pass a comparator: sort((a, b) => a - b).

  • One of the most common real-world JavaScript bugs.

sort()Comparator

Q18. hard

What is the output? console.log("5" === 5, "5" == 5);

const input = "5";        // from a form
if (input === 5) { }       // never runs!
if (Number(input) === 5) { }  // correct
  1. A false true
  2. B true true
  3. C false false
  4. D true false

Answer: A β€” false true

Strict comparison fails because the types differ. Loose comparison converts the string to a number first, so it succeeds. Data from input fields and APIs is often a string - a frequent source of this bug.

FormsInput validation

Q20. hard

What is the output? console.log(0.1 + 0.2 === 0.3);

console.log(0.1 + 0.2);   // 0.30000000000000004
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON);   // true
  1. A false - floating-point maths gives 0.30000000000000004
  2. B true
  3. C NaN
  4. D SyntaxError

Answer: A β€” false - floating-point maths gives 0.30000000000000004

Binary floating point cannot represent 0.1 and 0.2 exactly. Compare with a tolerance: Math.abs(a - b) < Number.EPSILON, or work in integers (cents instead of rupees).

Floating pointNumber.EPSILON

Q22. hard

What is the output? console.log(1 + "2" - 3);

  1. A 9 - 1 + "2" gives "12", then "12" - 3 converts back to 12 - 3
  2. B 0
  3. C "12-3"
  4. D NaN

Answer: A β€” 9 - 1 + "2" gives "12", then "12" - 3 converts back to 12 - 3

Left to right: + with a string concatenates to "12"; then - forces numeric conversion, giving 12 - 3 = 9. A perfect illustration of mixed coercion.

CoercionOperator order

Q24. hard

What is the output? console.log(!!"false", !!"0", !!0);

const flag = "false";
if (flag) { }                  // runs! (truthy string)
if (flag === "true") { }       // correct check
  1. A true true false - any non-empty string is truthy regardless of its content
  2. B false false false
  3. C true false false
  4. D false true true

Answer: A β€” true true false - any non-empty string is truthy regardless of its content

The strings "false" and "0" are non-empty, so they are truthy. Only the number 0 is falsy here. Reading "false" from an API and using it in an if is a common bug - compare explicitly instead.

TruthinessAPI data

Q26. hard

What is the output? console.log(typeof ("5" - 3), typeof ("5" + 3));

  1. A "number" "string"
  2. B "string" "string"
  3. C "number" "number"
  4. D "string" "number"

Answer: A β€” "number" "string"

Subtraction always produces a number (2), while + with a string produces a string ("53"). Same operands, different result types - the essence of JavaScript coercion.

typeofCoercion

Q28. hard

What is the output? console.log([1] == 1, [1,2] == "1,2");

  1. A true true - arrays convert to their comma-joined string, then compare
  2. B false false
  3. C true false
  4. D TypeError

Answer: A β€” true true - arrays convert to their comma-joined string, then compare

[1] becomes "1" then the number 1 - equal. [1,2] becomes "1,2", matching the string. Bizarre, but consistent with the coercion rules. Yet another reason to use ===.

Array coercionGotchas

Q30. hard

Why should you write === almost everywhere, in one sentence?

  1. A It compares without hidden conversions, so results are predictable and bug-free
  2. B It is faster to type
  3. C == was removed from the language
  4. D === works on more types

Answer: A β€” It compares without hidden conversions, so results are predictable and bug-free

Loose equality follows a complex conversion table that is not even transitive ("" == 0 and "0" == 0, but "" != "0"). Strict equality has one simple rule: same type, same value. Linters flag == for this reason.

Best practicesLinting

Practice β€œType Coercion & Equality” as a quiz