|$ curl https://forge-ai.dev/api/markdown?path=docs/js/data-types
$cat docs/javascript-—-data-types-&-coercion.md
updated This week·32 min read·published

JavaScript — Data Types & Coercion

JavaScriptTypesCoercionBeginnerBeginner to Advanced
Introduction

JavaScript has a dynamic type system — variables can hold values of any type, and the type can change at runtime. Despite this flexibility, every value has a well-defined type at any given moment. Understanding these types and how JavaScript coerces values between them is essential for writing predictable code.

JavaScript distinguishes between primitive types (immutable values stored directly) and reference types (objects stored by reference). Primitives include string, number, boolean, null, undefined, symbol, and bigint. Everything else — objects, arrays, functions, dates, maps, sets — is a reference type.

Type coercion — the automatic or intentional conversion of values from one type to another — is one of JavaScript's most misunderstood features. Knowing the rules of coercion helps you avoid bugs and write cleaner code.

dynamic-types.js
JavaScript
1// JavaScript's dynamic type system
2let value = "hello"; // string
3value = 42; // now a number
4value = true; // now a boolean
5value = { key: "val" }; // now an object
6value = null; // now null
7
8// typeof reveals the type at runtime
9console.log(typeof "hello"); // "string"
10console.log(typeof 42); // "number"
11console.log(typeof true); // "boolean"
12console.log(typeof {}); // "object"
13console.log(typeof undefined); // "undefined"
Primitive Types

Primitives are immutable values — once created, they cannot be changed. They are stored directly in the variable's memory location (on the stack). When you assign or compare primitives, you work with the actual value.

Typetypeof ResultExamplesNotes
string"string""hello", 'world', `template`UTF-16 encoded, immutable sequence of characters
number"number"42, 3.14, NaN, Infinity64-bit IEEE 754 floating point (no integer type)
boolean"boolean"true, falseLogical primitives for conditionals
undefined"undefined"undefinedDefault value of uninitialized variables and missing return
null"object"nullIntentional absence — typeof null is a historic bug
symbol"symbol"Symbol("id")Unique, immutable identifier (ES6) — guaranteed uniqueness
bigint"bigint"9007199254740991n, BigInt(42)Arbitrary precision integer (ES2020)

String

strings.js
JavaScript
1// Three quoting styles
2const single = 'Single quotes';
3const double = "Double quotes";
4const template = `Template literals — support interpolation and multiline`;
5
6const name = "Alice";
7const greeting = `Hello, ${name}!`; // Template interpolation
8console.log(greeting); // "Hello, Alice!"
9
10// Strings are immutable — methods return new strings
11const str = " JavaScript ";
12console.log(str.length); // 14 (including spaces)
13console.log(str.trim()); // "JavaScript"
14console.log(str.toUpperCase()); // " JAVASCRIPT "
15console.log(str.toLowerCase()); // " javascript "
16console.log(str.includes("Java")); // true
17console.log(str.slice(2, 12)); // "JavaScript"
18console.log("a".repeat(5)); // "aaaaa"
19console.log("hello".charAt(1)); // "e"
20
21// Template literal features
22const multiline = `
23 This is
24 a multiline
25 string
26`;
27console.log(`2 + 2 = ${2 + 2}`); // "2 + 2 = 4"
28
29// Tagged templates
30function highlight(strings, ...values) {
31 return strings.reduce((acc, str, i) =>
32 acc + str + (values[i] ? `<mark>${values[i]}</mark>` : ""), "");
33}
34const tagged = highlight`User ${name} is ${30} years old`;
35console.log(tagged);
36// "User <mark>Alice</mark> is <mark>30</mark> years old"

Number

numbers.js
JavaScript
1// JavaScript has ONE number type — 64-bit floating point (IEEE 754)
2const integer = 42; // Actually a float behind the scenes
3const float = 3.14;
4const scientific = 1.5e6; // 1500000
5const hex = 0xFF; // 255
6const octal = 0o77; // 63 (ES6)
7const binary = 0b1010; // 10 (ES6)
8const big = 1_000_000; // Numeric separators (ES2021) — readability
9
10// Special numeric values
11console.log(1 / 0); // Infinity
12console.log(-1 / 0); // -Infinity
13console.log(0 / 0); // NaN (Not a Number)
14console.log(Math.sqrt(-1)); // NaN
15console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
16console.log(Number.MIN_VALUE); // 5e-324
17console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 (2^53 - 1)
18console.log(Number.EPSILON); // 2.220446049250313e-16
19
20// Floating point precision issues
21console.log(0.1 + 0.2); // 0.30000000000000004 (not 0.3!)
22console.log(0.1 + 0.2 === 0.3); // false
23
24// Safe comparison for floats
25function approxEqual(a, b, epsilon = Number.EPSILON) {
26 return Math.abs(a - b) < epsilon;
27}
28console.log(approxEqual(0.1 + 0.2, 0.3)); // true
29
30// Number methods
31console.log(Number.isInteger(42)); // true
32console.log(Number.isFinite(Infinity)); // false
33console.log(Number.isNaN("NaN")); // false (no coercion)
34console.log(isNaN("NaN")); // true (coerces — avoid)
35console.log(parseInt("42px")); // 42
36console.log(parseFloat("3.14em")); // 3.14
37console.log((3.14159).toFixed(2)); // "3.14"

BigInt

bigint.js
JavaScript
1// BigInt — arbitrary precision for large integers
2const bigint = 9007199254740991n;
3const fromNumber = BigInt(42);
4const fromString = BigInt("9007199254740991");
5
6// Operations with BigInt
7console.log(bigint + 1n); // 9007199254740992n
8console.log(bigint * 2n); // 18014398509481982n
9
10// Cannot mix BigInt and regular Number
11console.log(bigint + 1); // TypeError: Cannot mix BigInt and other types
12
13// Comparisons work across types
14console.log(1n === 1); // false (different types)
15console.log(1n == 1); // true (loose equality coerces)
16
17// Only integers — no decimals
18// console.log(1.5n); // SyntaxError
19
20// Division truncates toward zero
21console.log(5n / 2n); // 2n

Symbol

symbols.js
JavaScript
1// Symbol — unique, immutable identifiers
2const sym1 = Symbol("description");
3const sym2 = Symbol("description");
4console.log(sym1 === sym2); // false — every Symbol is unique
5
6// Symbols as object keys (for "private" or metadata properties)
7const id = Symbol("id");
8const user = { name: "Alice", [id]: 12345 };
9console.log(user[id]); // 12345
10console.log(user.id); // undefined — not a string key
11
12// Symbols are not enumerable in for...in or Object.keys
13console.log(Object.keys(user)); // ["name"]
14console.log(Object.getOwnPropertySymbols(user)); // [Symbol(id)]
15
16// Well-known symbols — customize behavior
17const arr = [1, 2, 3];
18console.log(arr[Symbol.iterator]); // [Function: values]
19
20// Symbol.for — shared symbols across realms
21const globalSym = Symbol.for("app.role");
22const sameSym = Symbol.for("app.role");
23console.log(globalSym === sameSym); // true — same symbol

info

Use Number.isNaN() instead of the global isNaN(). The global isNaN() coerces values to numbers first — isNaN("hello") returns true because Number("hello") is NaN. Number.isNaN() does not coerce, so Number.isNaN("hello") is false.
Reference Types

Reference types store a reference (memory address) to the actual data, not the data itself. When you assign or compare reference types, you are working with references. This distinction is critical for understanding mutation, equality, and memory behavior.

Object

objects.js
JavaScript
1// Object literal — most common reference type
2const person = {
3 name: "Alice",
4 age: 30,
5 greet() {
6 console.log(`Hi, I'm ${this.name}`);
7 },
8};
9
10// Accessing properties
11console.log(person.name); // "Alice" — dot notation
12console.log(person["age"]); // 30 — bracket notation (for dynamic keys)
13
14// Adding and modifying properties
15person.city = "New York";
16person.age = 31;
17
18// Deleting properties
19delete person.city;
20
21// Property existence
22console.log("name" in person); // true
23console.log(person.hasOwnProperty("name")); // true
24
25// Object.keys, values, entries
26console.log(Object.keys(person)); // ["name", "age"]
27console.log(Object.values(person)); // ["Alice", 31]
28console.log(Object.entries(person)); // [["name","Alice"],["age",31]]
29
30// Merging objects
31const defaults = { theme: "dark", lang: "en" };
32const userPrefs = { theme: "light" };
33const config = { ...defaults, ...userPrefs };
34console.log(config); // { theme: "light", lang: "en" }

Array

arrays.js
JavaScript
1// Arrays — ordered, zero-indexed collections
2const fruits = ["apple", "banana", "cherry"];
3console.log(fruits[0]); // "apple"
4console.log(fruits.length); // 3
5
6// Adding and removing
7fruits.push("date"); // add to end — ["apple","banana","cherry","date"]
8fruits.pop(); // remove from end — returns "date"
9fruits.unshift("apricot"); // add to start
10fruits.shift(); // remove from start
11
12// Finding elements
13console.log(fruits.indexOf("banana")); // 1
14console.log(fruits.includes("apple")); // true
15console.log(fruits.find(f => f.startsWith("b"))); // "banana"
16console.log(fruits.findIndex(f => f.startsWith("c"))); // 2
17
18// Slicing and splicing
19console.log(fruits.slice(1, 3)); // ["banana", "cherry"] — non-destructive
20console.log(fruits); // original unchanged
21
22// Multi-dimensional arrays
23const matrix = [
24 [1, 2, 3],
25 [4, 5, 6],
26 [7, 8, 9],
27];
28console.log(matrix[1][2]); // 6
29
30// Array-like checks
31console.log(Array.isArray(fruits)); // true
32console.log(Array.isArray({})); // false

Map & Set

map-set.js
JavaScript
1// Map — key-value with ANY key type (not just strings)
2const map = new Map();
3const objKey = { id: 1 };
4const fnKey = () => {};
5
6map.set("string", "value");
7map.set(42, "number key");
8map.set(objKey, "object key");
9map.set(fnKey, "function key");
10
11console.log(map.get(42)); // "number key"
12console.log(map.get(objKey)); // "object key"
13console.log(map.has("string")); // true
14console.log(map.size); // 4
15map.delete(42);
16console.log(map.size); // 3
17
18// Map preserves insertion order
19for (const [key, value] of map) {
20 console.log(key, value);
21}
22
23// Set — unique values (no duplicates)
24const set = new Set([1, 2, 3, 3, 3, 4, 5]);
25console.log(set); // Set { 1, 2, 3, 4, 5 }
26console.log(set.size); // 5
27
28set.add(6);
29set.add(1); // ignored — already exists
30console.log(set.has(3)); // true
31set.delete(3);
32
33// Set iteration
34for (const value of set) {
35 console.log(value);
36}
37
38// Practical: deduplication
39const duplicates = [1, 2, 2, 3, 3, 3, 4];
40const unique = [...new Set(duplicates)];
41console.log(unique); // [1, 2, 3, 4]
42
43// Practical: set operations
44const a = new Set([1, 2, 3]);
45const b = new Set([3, 4, 5]);
46const union = new Set([...a, ...b]); // {1,2,3,4,5}
47const intersection = new Set([...a].filter(x => b.has(x))); // {3}

Date

dates.js
JavaScript
1// Date — working with dates and times
2const now = new Date();
3console.log(now.toString());
4console.log(now.toISOString());
5console.log(now.toLocaleDateString());
6
7// Creating dates
8const specific = new Date(2026, 6, 7, 14, 30, 0);
9// Note: months are 0-indexed (0 = January)
10const fromISO = new Date("2026-07-07T14:30:00Z");
11const fromMs = new Date(1780000000000);
12
13// Getting date components
14const d = new Date();
15console.log(d.getFullYear()); // 2026
16console.log(d.getMonth()); // 6 (July is 6)
17console.log(d.getDate()); // 7
18console.log(d.getDay()); // 2 (Tuesday — 0=Sun, 1=Mon, 2=Tue)
19console.log(d.getHours()); // 14
20console.log(d.getTime()); // milliseconds since epoch
21
22// Date arithmetic
23const tomorrow = new Date(now);
24tomorrow.setDate(now.getDate() + 1);
25console.log(diffInDays(d1, d2)); // helper needed
26
27// Timestamp comparison
28console.log(now.getTime() > specific.getTime());

warning

Use Map instead of plain objects when you need keys that are not strings, when you need to preserve insertion order, or when you frequently add/delete key-value pairs. Plain objects inherit properties from their prototype, which can cause unexpected behavior — Map has no prototype chain for its entries.
Type Coercion

Type coercion is JavaScript's automatic conversion of values from one type to another. It happens in three contexts: string coercion (when using + with a string), number coercion (for arithmetic, comparisons, and loose equality), and boolean coercion (in conditionals and logical operators).

String Coercion

string-coercion.js
JavaScript
1// String coercion happens with the + operator when one operand is a string
2console.log("Hello" + 42); // "Hello42"
3console.log("5" + 3); // "53"
4console.log("5" + true); // "5true"
5console.log("5" + null); // "5null"
6console.log("5" + undefined); // "5undefined"
7
8// Explicit string conversion
9console.log(String(42)); // "42"
10console.log(String(true)); // "true"
11console.log(String(null)); // "null"
12console.log(String(undefined)); // "undefined"
13console.log((42).toString()); // "42"
14
15// Template literals also coerce
16console.log(`Value: ${42}`); // "Value: 42"
17
18// String coercion is NOT the same as JSON serialization
19console.log(JSON.stringify(42)); // "42"
20console.log(JSON.stringify(null)); // "null"
21console.log(JSON.stringify(undefined)); // undefined (not "undefined"!)

Number Coercion

number-coercion.js
JavaScript
1// Number coercion — arithmetic operators (except + with strings)
2console.log("5" - 2); // 3
3console.log("5" * "2"); // 10
4console.log("10" / 2); // 5
5console.log("5" - true); // 4 (true → 1)
6console.log("5" - false); // 5 (false → 0)
7console.log("5" - null); // 5 (null → 0)
8
9// Unary plus — explicit number conversion
10console.log(+"42"); // 42
11console.log(+true); // 1
12console.log(+false); // 0
13console.log(+null); // 0
14console.log(+undefined); // NaN
15console.log(+"hello"); // NaN
16
17// Explicit conversion with Number()
18console.log(Number("42")); // 42
19console.log(Number("3.14")); // 3.14
20console.log(Number("")); // 0
21console.log(Number(" ")); // 0
22console.log(Number("42px")); // NaN
23console.log(Number(true)); // 1
24console.log(Number(null)); // 0
25console.log(Number(undefined)); // NaN
26
27// parseInt and parseFloat — more lenient than Number()
28console.log(parseInt("42px")); // 42
29console.log(parseInt(" 42 ")); // 42
30console.log(parseInt("3.14")); // 3 (stops at decimal)
31console.log(parseFloat("3.14em")); // 3.14
32console.log(parseInt("abc")); // NaN
33
34// parseInt with radix — always specify!
35console.log(parseInt("0xFF", 16)); // 255
36console.log(parseInt("1010", 2)); // 10
37console.log(parseInt("077", 10)); // 77 (without radix: 63 in old engines)

Boolean Coercion & Truthy/Falsy

boolean-coercion.js
JavaScript
1// Falsy values — coerce to false in boolean contexts
2console.log(Boolean(false)); // false
3console.log(Boolean(0)); // false
4console.log(Boolean(-0)); // false
5console.log(Boolean("")); // false
6console.log(Boolean(null)); // false
7console.log(Boolean(undefined)); // false
8console.log(Boolean(NaN)); // false
9
10// Everything else is truthy
11console.log(Boolean("false")); // true (non-empty string!)
12console.log(Boolean("0")); // true (non-empty string!)
13console.log(Boolean([])); // true (empty array is truthy)
14console.log(Boolean({})); // true (empty object is truthy)
15console.log(Boolean(42)); // true
16console.log(Boolean(Infinity)); // true
17
18// Falsy check patterns
19const name = "";
20if (name) {
21 console.log("This never runs — empty string is falsy");
22}
23
24// Truthy guard
25const userInput = " ";
26if (userInput.trim()) {
27 console.log("User entered non-whitespace");
28}
29
30// Double NOT — explicit boolean coercion
31const value = 0;
32console.log(!!value); // false
33console.log(!!"hello"); // true
34
35// Boolean() — explicit conversion
36console.log(Boolean(1)); // true
37
38// Logical operators return the actual value, not a boolean
39console.log("hello" && 42); // 42 (last truthy)
40console.log(null || "default"); // "default" (first truthy)
41console.log(0 ?? "default"); // 0 (nullish coalescing — only null/undefined)

best practice

Use explicit coercion (String(), Number(), Boolean()) instead of relying on implicit coercion. Explicit conversions make your intent clear and reduce the chance of bugs from JavaScript's surprising coercion rules.
typeof vs instanceof

typeof and instanceof are two operators for checking types. typeof works on primitives and returns a string. instanceof checks whether an object is an instance of a constructor in its prototype chain.

OperatorWorks OnReturnsExample
typeofAny valuestring (type name)typeof 42 → "number"
instanceofObjects onlybooleanarr instanceof Array → true
typeof-instanceof.js
JavaScript
1// typeof — returns type as a string
2console.log(typeof 42); // "number"
3console.log(typeof "hello"); // "string"
4console.log(typeof true); // "boolean"
5console.log(typeof undefined); // "undefined"
6console.log(typeof Symbol()); // "symbol"
7console.log(typeof 42n); // "bigint"
8console.log(typeof null); // "object" (historic bug)
9console.log(typeof {}); // "object"
10console.log(typeof []); // "object"
11console.log(typeof function(){}); // "function"
12
13// instanceof — checks prototype chain
14console.log([] instanceof Array); // true
15console.log({} instanceof Object); // true
16console.log(new Date() instanceof Date); // true
17console.log(/regex/ instanceof RegExp); // true
18
19// instanceof with custom constructors
20class Animal {}
21class Dog extends Animal {}
22const dog = new Dog();
23console.log(dog instanceof Dog); // true
24console.log(dog instanceof Animal); // true
25console.log(dog instanceof Object); // true
26
27// instanceof pitfalls — across realms (iframes, windows)
28const iframe = document.createElement("iframe");
29document.body.appendChild(iframe);
30const IframeArray = iframe.contentWindow.Array;
31const arr = new IframeArray(1, 2, 3);
32console.log(arr instanceof Array); // false (different realm!)
33console.log(Array.isArray(arr)); // true (works across realms)
34
35// typeof pitfalls — the null bug
36const value = null;
37console.log(typeof value === "object"); // true — use value === null instead
38
39// Checking for array
40console.log(Array.isArray([])); // true — best practice
41console.log(typeof [] === "object"); // true — not helpful
🔥

pro tip

Use Array.isArray() to check for arrays (works across realms). Use value === null to check for null. Use typeof for primitive checks. Use instanceof for custom class instances. Use Object.prototype.toString.call() for a more robust type check: Object.prototype.toString.call([]) === "[object Array]".
Value vs Reference

Understanding the difference between value types (primitives) and reference types (objects) is fundamental to JavaScript. Primitives are compared by value; objects are compared by reference. This distinction affects assignment, comparison, and function parameter behavior.

value-vs-reference.js
JavaScript
1// Primitives — compared by VALUE
2const a = 42;
3const b = 42;
4console.log(a === b); // true — same value
5
6const s1 = "hello";
7const s2 = "hello";
8console.log(s1 === s2); // true — same value
9
10// Primitives are copied by value
11let x = 10;
12let y = x; // y gets a COPY of x's value (10)
13x = 20;
14console.log(y); // 10 — y is unaffected
15
16// Objects — compared by REFERENCE
17const obj1 = { value: 42 };
18const obj2 = { value: 42 };
19console.log(obj1 === obj2); // false — different references
20
21const obj3 = obj1; // obj3 gets a COPY of the reference
22console.log(obj1 === obj3); // true — same reference
23
24// Objects are passed by reference (copy of the reference)
25function mutate(obj) {
26 obj.modified = true;
27 obj = { newObj: true }; // reassigning the parameter — does NOT affect original
28}
29const original = { value: 1 };
30mutate(original);
31console.log(original.modified); // true
32console.log(original.newObj); // undefined
33
34// Shallow vs deep copy
35const nested = { a: 1, b: { c: 2 } };
36const shallow = { ...nested }; // shallow copy
37shallow.a = 99; // OK — does not affect nested
38shallow.b.c = 999; // Mutates nested! Shared reference
39console.log(nested.b.c); // 999
40
41const deep = JSON.parse(JSON.stringify(nested)); // deep copy
42deep.b.c = 888;
43console.log(nested.b.c); // 999 (unchanged after shallow mutation)

danger

Mutation of shared references is one of the most common sources of bugs in JavaScript. When you pass an object to a function, the function can mutate the original. If this is not intended, create a copy first. Use { ...obj } for shallow copies and structuredClone() or libraries like Lodash for deep cloning.
NaN, Infinity & Edge Cases

NaN

nan-edge-cases.js
JavaScript
1// NaN — the only value not equal to itself
2console.log(NaN === NaN); // false (I)
3console.log(NaN !== NaN); // true (I know)
4
5// Checking for NaN
6console.log(Number.isNaN(NaN)); // true — use this
7console.log(Number.isNaN("hello")); // false — no coercion
8console.log(isNaN("hello")); // true — coerces! Avoid
9
10// Operations that produce NaN
11console.log(0 / 0); // NaN
12console.log(Math.sqrt(-1)); // NaN
13console.log(parseInt("abc")); // NaN
14console.log(undefined + 1); // NaN
15console.log("hello" - 1); // NaN
16
17// NaN in arrays — indexOf/findIndex won't find NaN
18const arr = [1, NaN, 2];
19console.log(arr.indexOf(NaN)); // -1 (not found!)
20console.log(arr.includes(NaN)); // true (ES2016 — uses SameValueZero)
21
22// Using Object.is for NaN comparison
23console.log(Object.is(NaN, NaN)); // true
24console.log(Object.is(0, -0)); // false

Infinity & -0

infinity-edge-cases.js
JavaScript
1// Infinity and -Infinity
2console.log(1 / 0); // Infinity
3console.log(-1 / 0); // -Infinity
4console.log(Number.MAX_VALUE * 2); // Infinity
5
6console.log(Infinity > 1e308); // true
7console.log(-Infinity < -1e308); // true
8console.log(Infinity + 1); // Infinity
9console.log(Infinity - Infinity); // NaN
10console.log(1 / Infinity); // 0
11
12// isFinite — safe check for finite numbers
13console.log(isFinite(42)); // true
14console.log(isFinite(Infinity)); // false
15console.log(isFinite(NaN)); // false
16console.log(isFinite("42")); // true (coerces)
17
18// Negative zero (-0)
19console.log(-0); // -0
20console.log(Object.is(0, -0)); // false
21console.log(0 === -0); // true (=== treats them as equal)
22
23// When -0 appears
24console.log(-0); // -0
25console.log(1 / -Infinity); // -0
26console.log(-1 * 0); // -0
27
28// -0 serialization
29console.log(String(-0)); // "0"
30console.log(JSON.stringify(-0)); // "0"
31console.log(Object.is(-0, 0)); // false

warning

The fact that NaN !== NaN is a consequence of IEEE 754 floating point standard, not a JavaScript quirk. Always use Number.isNaN() to check for NaN. For strict equality that handles NaN and -0 correctly, use Object.is().
Type Conversion Best Practices

Essential Guidelines

Always use === and !== — never rely on loose equality's coercion rules
Use explicit coercion: String(), Number(), Boolean() instead of relying on implicit conversion
Use Number.isNaN() not isNaN() — the global isNaN() coerces values first
Use Number.isFinite() for checking finite numbers — accounts for NaN and Infinity
Use Array.isArray() not typeof for array checks — typeof returns 'object' for arrays
Use value === null to check for null — do not rely on !value which catches all falsy values
Prefer Map over plain objects when keys are dynamic, non-string, or frequently added/removed
Use structuredClone() or JSON.parse(JSON.stringify()) for deep cloning objects
Be aware of floating point precision — use epsilon comparison for decimal arithmetic
Use BigInt for integers beyond Number.MAX_SAFE_INTEGER (9,007,199,254,740,991)

Common Pitfalls

✗ typeof null === "object"

console.log(typeof null); // "object" — it's a bug from 1995

Use value === null to check for null, never typeof value === "object".

✗ Floating Point Arithmetic

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

Never compare floats directly. Use an epsilon tolerance or a decimal library for financial calculations.

✗ Loose Equality Surprises

console.log([] == false); // true. console.log([1] == 1); // true

The == operator follows complex coercion rules. Always use === for predictable comparisons.

✗ NaN !== NaN

if (myValue === NaN)

NaN is never equal to itself. Use Number.isNaN(myValue) or Object.is(myValue, NaN).

best practice

The golden rule of JavaScript types: be explicit. Explicit type conversions make code readable and predictable. The only people who benefit from implicit coercion are attackers looking for XSS vectors. The rest of us prefer clarity.
$Blueprint — Engineering Documentation·Section ID: JS-DTYPES·Revision: 1.0