Module: JavaScript
JavaScript·044·8 MIN READ

044: Values and Data Types

TOPICS COVERED: Values and Data Types

Outcomes

By the end of this lesson, you can:

  • recognize string, number, Boolean, undefined, null, object, and array values;
  • explain the difference between primitive and object values at a beginner level;
  • inspect values with typeof and identify its important exceptions;
  • choose a suitable type for realistic data; and
  • avoid confusing a value's type with the variable that currently holds it.

Prerequisites and Retrieval

Retrieve const, let, initialization, reassignment, and block scope from 043.

  1. Which declaration should be the default?
  2. Which declaration permits a new assignment?
  3. Is "42" visibly the same kind of literal as 42?

Use a fresh browser console or module script. Predict every type before running the examples.

Terms

  • data type: The classification of values: seven primitives plus Object. — Source: MDN: Data structures
  • primitive: “Data that is not an object and has no methods”: string, number, bigint, boolean, undefined, symbol, null. — Source: MDN: Primitive
  • string: An immutable sequence of characters representing text. — Source: MDN: String
  • number: Double-precision 64-bit IEEE value including integers and NaN/Infinity. — Source: MDN: Number
  • Boolean: Logical type with exactly two values: true and false. — Source: MDN: Boolean
  • undefined: Value of a declared-but-uninitialized variable; also missing property access result. — Source: MDN: undefined
  • null: A deliberate “no value” marker; typeof null returns "object" historically. — Source: MDN: null
  • object: A collection of properties keyed by strings/symbols; arrays and functions are objects. — Source: MDN: Object
  • array: An ordered list-like object with numeric indices starting at 0. — Source: MDN: Array
  • dynamic typing: Types attach to values, so one variable can hold different types over time. — Source: MDN: Data structures
  • typeof: Operator returning a string describing a value’s type. — Source: MDN: typeof
  • Primitive (official): "A primitive is data that is not an object and has no methods; there are 7 primitives: string, number, bigint, boolean, undefined, symbol, null." — Source: MDN: Primitive
  • Reference: "A reference is a pointer to an object in memory; copying a reference copies the pointer, not the object." — Source: MDN: Data structures — Objects

Beginner Explanation and Mental Model

Programs represent facts as values. Choosing a type is like choosing the correct container on a form. A name is text, a price is numeric, and an enrollment state is Boolean. Type matters because operations have meanings based on their operands: 10 + 5 calculates 15, while "10" + "5" joins text into "105".

JavaScript currently defines seven primitive types: string, number, Boolean, undefined, null, BigInt, and Symbol. Today's required set focuses on the first five. BigInt and Symbol solve specialized problems and are not needed for these beginner models. Everything else belongs to the object type. Arrays look and act like lists, but technically they are objects.

js
const userName = "Leela";   // string
const score = 88.5;             // number
const passed = true;            // boolean
let feedback;                   // undefined
const selectedContact = null;    // null
const user = { name: "Leela" }; // object
const skills = ["HTML", "CSS"];   // array object

undefined commonly means "not supplied or not initialized." null is normally assigned deliberately to mean "known to be absent." They are different values: null === undefined is false. Do not use the string "null" or "undefined" to represent absence; those are ordinary text.

Primitive values behave as indivisible values for today's mental model. Objects group data and are handled through references. If two variables refer to the same object, mutation through one reference is visible through the other. Detailed object behavior comes later.

Inspecting types

typeof returns a string:

js
console.log(typeof "hello"); // string
console.log(typeof 12);      // number
console.log(typeof false);   // boolean
console.log(typeof undefined); // undefined

Two important exceptions must be memorized rather than "fixed":

js
console.log(typeof null);     // object (historical behavior)
console.log(typeof [1, 2]);   // object
console.log(Array.isArray([1, 2])); // true

Use value === null to test specifically for null, and Array.isArray(value) to identify arrays. typeof is still useful; it is simply not a complete classifier.

JavaScript is dynamically typed. The binding does not receive a permanent declared type:

js
let result = 10;
result = "complete";

This is legal, but changing a variable's meaning and type usually harms readability. Prefer one stable meaning per variable.

Worked Example: User Profile Values

Run this complete example:

js
const userName = "Nila";
const userAge = 20;
const isEnrolled = true;
let latestScore;
const contact = null;
const profile = { city: "Chennai" };
const subjects = ["HTML", "CSS", "JavaScript"];

console.log(userName, typeof userName);
console.log(userAge, typeof userAge);
console.log(isEnrolled, typeof isEnrolled);
console.log(latestScore, typeof latestScore);
console.log(contact, typeof contact);
console.log(profile, typeof profile);
console.log(subjects, typeof subjects);
console.log("Is subjects an array?", Array.isArray(subjects));
console.log("Is contact null?", contact === null);

Expected output (object formatting varies by browser):

text
Nila string
20 number
true boolean
undefined undefined
null object
{city: "Chennai"} object
["HTML", "CSS", "JavaScript"] object
Is subjects an array? true
Is contact null? true

Notice that typeof itself returns text such as "number". It does not modify the value. latestScore has no initializer, so let gives it the value undefined. contact is deliberately empty, so it is initialized to null. The object and array both produce "object", and the dedicated array check distinguishes them.

Intermediate Example: Validate a Data Shape

Use only simple Boolean checks here; branching is taught in 047 after coercion and operators. Focus on the type results:

js
const product = {
  name: "Keyboard",
  price: 1500,
  inStock: true,
  discount: null,
};

const tags = ["accessory", "input"];

const hasValidName = typeof product.name === "string";
const hasValidPrice = typeof product.price === "number";
const hasStockFlag = typeof product.inStock === "boolean";
const hasNoDiscount = product.discount === null;
const hasTagList = Array.isArray(tags);

console.log("Name valid:", hasValidName);
console.log("Price valid:", hasValidPrice);
console.log("Stock flag valid:", hasStockFlag);
console.log("No discount:", hasNoDiscount);
console.log("Tags valid:", hasTagList);

Expected output is five lines ending in true. Type checking does not prove all business validity. For example, -500 is still a number, and an empty string is still a string. Later validation combines type checks with range and content rules.

Also remember that NaN has type "number". It represents an invalid numeric result. Use Number.isNaN(value) when that distinction matters; do not compare with value === NaN, which is always false.

Optional Advanced Extension: Primitive Copy vs Shared Reference

js
let firstScore = 80;
let copiedScore = firstScore;
copiedScore = 95;

const firstList = ["HTML"];
const sharedList = firstList;
sharedList.push("CSS");

console.log(firstScore, copiedScore);
console.log(firstList);
console.log(firstList === sharedList);

Expected output:

text
80 95
["HTML", "CSS"]
true

Assigning a primitive copies its value for this practical model. Assigning an object copies a reference, so both bindings identify the same array. This is enough reference knowledge for today; deep and shallow copying comes later.

Interview focus: values, references, and ownership

JavaScript is pass-by-value. For a primitive, the value passed to a function is the primitive itself. For an object, the value passed is a copy of the reference to that object. This is why interview answers should avoid saying simply "objects are passed by reference": the parameter receives its own value, but that value points at the same object.

js
function change(score, user) {
  score = 100;
  user.name = "Mina";
  user = { name: "Replacement" };
}

const score = 60;
const user = { name: "Ravi" };
change(score, user);

console.log(score);       // 60: the parameter was reassigned
console.log(user.name);   // Mina: both references reached the same object

The follow-up is usually: "How would you prevent the function from changing the caller’s object?" Return a new object, or make an explicit copy at the boundary. Do not promise that const solves this; const protects a binding from reassignment, not the object it names.

js
function rename(user, name) {
  return { ...user, name };
}

const nextUser = rename(user, "Leela");
console.log(nextUser === user); // false

This pass-by-value distinction also explains why changing a parameter's reference does not replace the caller's variable, while changing a property can be visible to the caller.

Deep Dive: Primitives, Identity, BigInt, and Symbol

Primitive values are immutable values. Objects are reference values with identity.

js
let first = "tea";
let second = first;
second = "coffee";

console.log(first); // "tea"

Compare that with an object:

js
const firstOrder = { total: 120 };
const secondOrder = firstOrder;

secondOrder.total = 150;

console.log(firstOrder.total); // 150

Both variables point to the same object.

BigInt

number is an IEEE-754 floating-point value. Very large integers can lose precision.

js
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991

const ledgerId = 9007199254740993n;
console.log(ledgerId + 1n);

Do not mix number and bigint in arithmetic without explicit conversion.

js
// 10n + 5 // TypeError
Number(10n) + 5;

Symbol

Symbols are unique primitive values, commonly used for collision-resistant property keys and language protocols.

js
const internalId = Symbol("internalId");

const order = {
  number: "ORD-1001",
  [internalId]: 8472,
};

console.log(order.number);
console.log(order[internalId]);

Symbol.iterator is especially important later because it defines how objects participate in for...of.

typeof edge cases worth remembering

js
typeof null;           // "object" — historical quirk
typeof [];             // "object"
Array.isArray([]);     // true
typeof function () {}; // "function"
typeof 1n;             // "bigint"
typeof Symbol();       // "symbol"

Use the inspection tool that matches the question you are actually asking.

Mistakes and Debugging

  • Forgetting quotes: const city = Chennai; looks for a variable named Chennai. Use "Chennai" for text.
  • Quoting numbers: a price of "500" is text and may concatenate. Store numeric facts as 500.
  • Quoting Booleans: "false" is a non-empty string, not the Boolean false.
  • Assuming typeof null is "null": test with value === null.
  • Assuming arrays have typeof result "array": use Array.isArray().
  • Treating undefined and undeclared as identical: an initialized/declared variable may contain undefined; reading a completely undeclared name throws ReferenceError.
  • Using typeof as full validation: combine it later with ranges, emptiness checks, and domain rules.
  • Relying on coercion: convert inputs explicitly at system boundaries instead of hoping operators infer intent.

Log both value and type while debugging: console.log("price", price, typeof price);. Check the earliest point where the actual type differs from the expected type.

Best Practices

  • Model text as strings, quantities as numbers, states as Booleans, intentional absence as null, and ordered collections as arrays.
  • Use lowercase true, false, null, and undefined.
  • Prefer null only when the application deliberately records absence; do not sprinkle it as a universal default.
  • Do not explicitly assign undefined unless an API contract requires it.
  • Use Array.isArray() for arrays and strict equality for null.
  • Keep each variable's meaning and expected type stable.
  • Avoid wrapper objects such as new Boolean(false) and new String("text"); use primitives.
  • Treat browser form input as strings until explicitly validated and converted.

Tiered Exercises

Core

Create one value of each required type: string, number, Boolean, undefined, null, object, and array. Log each value and its typeof result. Use Array.isArray() for the list.

Practice

Model a book using a title, page count, availability flag, optional borrower, a small details object, and an array of genres. Choose types and print checks that prove your choices.

Professional Extension

Predict the results of typeof null, typeof [], Array.isArray({}), Array.isArray([]), typeof NaN, and null === undefined. Then verify and explain every result.

Complete Solutions

js
const textValue = "JavaScript";
const numberValue = 31;
const booleanValue = true;
let undefinedValue;
const nullValue = null;
const objectValue = { topic: "types" };
const arrayValue = [31, 32, 33];

console.log(textValue, typeof textValue);
console.log(numberValue, typeof numberValue);
console.log(booleanValue, typeof booleanValue);
console.log(undefinedValue, typeof undefinedValue);
console.log(nullValue, typeof nullValue);
console.log(objectValue, typeof objectValue);
console.log(arrayValue, typeof arrayValue, Array.isArray(arrayValue));
js
const title = "Clean Code Basics";
const pageCount = 240;
const isAvailable = true;
const borrower = null;
const details = { language: "English" };
const genres = ["technology", "education"];

console.log(typeof title === "string");
console.log(typeof pageCount === "number");
console.log(typeof isAvailable === "boolean");
console.log(borrower === null);
console.log(typeof details === "object" && details !== null);
console.log(Array.isArray(genres));

Every line prints true.

js
console.log(typeof null);       // object: historical exception
console.log(typeof []);         // object: arrays are objects
console.log(Array.isArray({})); // false
console.log(Array.isArray([])); // true
console.log(typeof NaN);        // number
console.log(null === undefined); // false: different primitive values

Recap and Exit Questions

Types describe values and their behavior. Strings, numbers, Booleans, undefined, and null are primitives. Objects group data, and arrays are specialized objects. typeof is useful when its null and array exceptions are understood.

  1. Why should a price usually be a number rather than a numeric string?
  2. How do undefined and null differ in intent?
  3. What does typeof return, and what type is that return value?
  4. How should code detect an array?
  5. What does dynamic typing mean?

Official References

References checked 2026-08-24.