2. Data Types & Variables
Table of Contents:
Summary
Data types are categories of values in JavaScript. There are 5 primitive types (String, Number, Boolean, undefined, null) and 3 reference types (Object, Array, Function). Knowing the type of a value helps determines how you can use that value. Choosing the right type to represent your data is essential.
Operators are symbols (e.g.
+
,>=
,&&
) that generate new data from existing values. Arithmetic, comparison, and logical operators allow you to perform calculations and make decisions.Type coercion is the process of converting a value from one data type to another, sometimes automatically. Values can be "truthy" or "falsy" depending on their content.
Variables are named containers for data. You can reference and reassign variables to store and update information in your program.
There are four ways to declare variables:
const
(preferred for values that don't change),let
(for values that do change),var
(legacy, avoid using), and global variables (avoid using).
Scope refers to where a variable is declared. It impacts the "reachability" of the variable (where it can be referenced).
Hoisting allows some variables and functions to be referenced before they are declared, which can lead to confusing bugs. Prefer
const
andlet
to avoid hoisting
Computation is All About Data
Every computational device, even the earliest device the abacus, is used to manipulate and generate data.

Our modern computers, while much more powerful, are still oriented around this singular goal: manipulating and generating data.
What has changed and evolved over time is what we do with those calculations and how quickly our devices can perform them. Here are some modern applications of how our computers make use of data:
Rendering images & video: Calculating pixel positions, color values, and frame rates turns raw math into Netflix streams and 3D games.
Navigation systems: Continuous GPS data (latitude/longitude as numbers) is transformed into live maps, directions, and traffic updates.
Social media: Posts are stored as text data, likes as counts, and relationships as graph data — powering your feed and recommendations.
Online shopping: Prices (numbers), product info (strings), and cart contents (arrays of objects) are combined to let you browse, compare, and buy.
Music & audio: Sound waves are stored as numerical data, then processed and streamed as songs, podcasts, and phone calls.
Healthcare & fitness apps: Heart rate, steps, and sleep cycles (all data points) are tracked and analyzed to monitor your health.
Artificial intelligence: Images, text, or speech are converted into numbers (vectors, matrices) that models process to recognize faces, generate text, or translate languages.
In this lesson, we'll learn about the different types of data, how our computers store data in variables, and then the many ways that we can compute new data.
Data Types
All values have a data type that determines what you can do with that value.
For example, you can use numbers to perform mathematical calculations and can use strings to construct messages. Knowing the different data types allows you to choose the best data type for your particular use case.
There are five main primitive data types: Number, String, Boolean, undefined
, and null
String
"hello"
or '@abc123'
Text (any sequence of characters)
Usernames, chat messages, product descriptions, search queries
Number
50
or 10.5
or -2
Numeric values
Scores in a game, count of likes on a post, timers
Boolean
true
or false
Truth value
Login status, feature toggles (dark mode on/off), win/lose conditions
Undefined
undefined
A variable that has been declared but not yet given a value
“Not yet set” values
Null
null
Intentional absence of a value
Representing “no result”
There are also three reference data types: Objects, Arrays, and Functions.
Object
{ name: "Alex", age: 25 }
A collection of data relating to one "thing"
Storing user profile data, storing data about product (name, description, price, etc...)
Array
[ "apple", "banana", "cherry" ]
An ordered list of similar values
Storing lists (shopping cart items, game high scores, chat messages)
Function
function greet() { console.log("Hi!"); }
A reusable block of code
Performing actions, handling events, calculations
Operators
Now that we know the types of data, let's use our computers to generate data with operators!
An operator is a symbol that uses data values to generate a new piece of data, forming an expression:
5 + 2; // the value 7 is created by the + operator in this expression
Let's start by reviewing the basic categories of operators: arithmetic, comparison, and logical.
Challenge: Can you tell what each expression will produce?
// Arithmetic Operators
console.log("Arithmetic Operators:");
console.log(5 + 2); // Addition
console.log(5 - 2); // Subtraction
console.log(5 * 2); // Multiplication
console.log(5 / 2); // Division
console.log(5 % 2); // Modulus (remainder)
console.log(5 ** 2); // Exponentiation
// Comparison Operators
console.log("\nComparison Operators:");
console.log(5 > 2); // x greater than y
console.log(5 < 2); // x less than y
console.log(5 >= 5); // x greater than or equal to y
console.log(5 <= 4); // x less than or equal to y
console.log(5 == "5"); // x is loosely equal to y
console.log(5 === "5"); // x is strictly equal to y
console.log(5 != 2); // x is loosely not equal to y
console.log(5 !== "5"); // x is strictly not equal to y
// Logical Operators
console.log("\nLogical Operators:");
console.log(true && false); // And
console.log(true || false); // Or
console.log(!true); // Not
Ternary Operator
The ternary operator boolExpression ? valA : valB
produces one of two values based on the boolExpression
value:
valA
is produced if theboolExpression
evaluates totrue
valB
is produced if theboolExpression
evaluates tofalse
console.log(5 % 2 === 0 ? "it is even!" : "it is odd!");
typeof Operator
The typeof
operator returns the type of a given value as a string.
console.log(typeof "hi"); // Prints "string"
console.log(typeof 4); // Prints "number"
console.log(typeof NaN); // Prints "number"
console.log(typeof true); // Prints "boolean"
console.log(typeof undefined); // Prints "undefined"
console.log(typeof console.log); // Prints "function"
// Beware: objects, null, and arrays all show up as "object"
console.log(typeof {}); // Prints "object"
console.log(typeof null); // Prints "object"
console.log(typeof []); // Prints "object"
Resolution Order of Operations
Operators can be combined to form complex expressions. In these cases, understanding the order in which operators are evaluated — also called operator precedence — is crucial.
Let's look at this code snippet as an example, what is the value of result
?:
const result = Math.random() > 0.5 ? "Heads" : "Tails";
Below is the order of precedence:
Function calls are evaluated first
Then arithmetic operators.
*
,/
,%
are evaluated before+
and-
.Followed by comparison operators. Relational operators (
<
,<=
,>
,>=
) are evaluated before equality operators (===
,!==
,==
,!=
)Then logical operators. AND (
&&
) has higher precedence than logical OR (||
).Ternary operator (
x ? y :z
) and assignment happens last (=
)
Parentheses ()
can always be used to override the default order and make the evaluation order explicit.
const result = Math.random() > 0.5 ? "Heads" : "Tails";
Challenge: what values are produced by the code snippet below?
// Arithmetic
console.log(5 + 2 * 3);
console.log((5 + 2) * 3);
// Comparison
console.log(5 + 2 > 6);
console.log(5 + (2 > 6));
// Logical
console.log(true || false && false);
console.log((true || false) && false);
// Combined
console.log(5 > 3 && 2 + 2 === 4);
console.log((5 > 3 && 2 + 2) === 4);
console.log(Math.ceil(Math.random() * 6))
Type Coercion & Truthy vs. Falsy
We can "coerce" a value of one data type to become another data type using type casting functions:
// EVerything can easily be turned into a string
console.log(String(1)) // -> "1"
console.log(String(true)) // -> "true"
// Not everything becomes a number in a nice way
console.log(Number(false)) // -> 0
console.log(Number("hello")) // -> NaN (not a number)
// Values that are "non-values" or "empty values" are considered "falsy"
// All other values are "truthy"
console.log(Boolean(0)) // -> false
console.log(Boolean('')) // -> false
console.log(Boolean(null)) // -> false
console.log(Boolean(undefined)) // -> false
console.log(Boolean(100)) // -> true
console.log(Boolean('hello')) // -> true
In some cases, type coercion happens automatically, potentially without us knowing.
For example, what is the result of the expression below? What data type is produced? Do you think we should even be allowed to do something like this?
console.log("1" + 1);
Variables
A Variable in JavaScript is a named container for data. By labeling our data, variables enable us to perform a series of computations in a program and "save" our progress along the way. Descriptive variable names dramatically improve the readability of our code.
Consider the two approaches below to produce the same result. The first does not use variables while the second does. What are the tradeoffs of each approach?
Approach 1: No Variables
console.log(`The sum of 4 + 3 + 2 + 1 is ${4 + 3 + 2 + 1} and the average is ${(4 + 3 + 2 + 1) / 4}`);
// Output: The sum of 4 + 3 + 2 + 1 is 10 and the average is 2.5
Approach 2: Variables
const sum = 4 + 3 + 2 + 1;
const average = sum / 4;
const message = `The sum of 4 + 3 + 2 + 1 is ${sum} and the average is ${average}`;
console.log(message);
// Output: The sum of 4 + 3 + 2 + 1 is 10 and the average is 2.5
Using Variables: Declare, Assign, Reference
There are three things we can do with variables:
Create a new variable ("declare the variable"). Use
let
orconst
.Give the variable a new value to hold ("assign the variable a value"). Only possible with
let
variables.Use the value held by the variable ("reference the variable")
// Declare a variable without an initial value
let count;
// Assigning the variable the value 0
count = 0;
// Reference the count variable to access its current value, 0
console.log(`count starts at ${count}`);
// Reassign the variable to hold a new value: 1
count = 1;
// Reference the count variable again to access its current value, 1
console.log(`count is now ${count}`);
We can even reference the current value of a variable to calculate the new value we assign to it:
// The right side of `=` resolves before reassignment. Count is 2
count = count + 1;
// The "increment" operator is the same as `count = count + 1`. Count is 3
count++;
// The "addition assignment" operator is the same as `count = count + 3`. Count is 6
count += 3;
console.log(`count is now ${count}`); // Output: count is now 6
Scope
Scope refers to where a variable is declared. The scope of the variable impacts the "reachability" of the variable (where it can be referenced).
For example, a variable declared in the scope of a function can only be referenced within that function. It is not reachable outside of the function.
const printX = () => {
// x is reachable anywhere in this function
const x = 10;
console.log(x);
}
printX();
console.log(x); // ReferenceError: x is not defined
Variables can be declared at the following levels of scope, listed from the least reachability to the most reachability:
Block-Scoped Variables — Variables declared within a "block statement"
{}
(e.g.if
,if else
,else
,for
,while
, etc...).Function-Scoped Variables — Variables and parameters declared within a function.
Module-Scoped Variables — Variables declared within a file and outside of any function.
Global-Scoped Variables — Variables provided by the runtime environment (Node, the Browser). These are things like the
global
andwindow
objects. Avoid adding data to these objects.
Scopes can contain other scopes. For example, a file can contain a function that has an if
block statement inside. Variables declared in the "outer" scope can be referenced anywhere within the "inner" scopes, but not vice-versa.
// myName is module-scoped. Reachable anywhere in this file.
const myName = 'John';
const sayHi = () => {
// `myName` is reachable anywhere within this file, even in lower scopes like in this function
console.log(`Hi, my name is ${myName}`)
}
const greetFriend = (friend) => {
// Parameters like `friend` are function-scoped. Reachable anywhere in this function.
if (!friend) {
// message is block-scoped. Reachable only in this block.
const message = "I can't say hi if I don't know your name!";
console.log(message);
} else {
// message is block-scoped. Reachable only in this block.
const message = `Hi, ${friend}, I'm ${myName}. Nice to meet you.`;
console.log(message);
}
}
greetFriend("");
// Output: I can't say hi if I don't know your name!
greetFriend('Jane');
// Output: "Hi, Jane, I'm John. Nice to meet you."
// We get ReferenceErrors if we try to reference variables out of scope.
console.log(message, myName);
When a variable that is out of scope is referenced, a ReferenceError
is thrown.
The Four Ways To Declare Variables
There are 4 ways to declare a new variable, but only the first two of should be used:
const
declares a block-scoped variable that cannot be reassigned. This should be your go-to variable declaration.let
declares a re-assignable block-scoped variable. Use only when reassignment is necessary.var
declares a re-assignable, hoisted, function-scoped variable. Do not usevar
. Hoisting and function-scoped variables can cause unexpected behavior (read more below).Global-scoped variables are declared without a keyword. Do not use global variables.
// Good
const myName = 'John';
// Uncaught TypeError: Assignment to constant variable. Hmm, time to use a let.
myName = 'Johnny';
// Also good
let myAge = 101;
// No error!
myAge = 5;
// Bad
var status = 'happy';
// Very bad
globalStatus = 'sad';
Hoisting: Why We Don't Use var
var
Hoisting is a feature of JavaScript that allows certain variables/functions to be referenced before they are declared.
Variables declared with the
var
keyword and Functions declared with thefunction
keyword are hoisted.Variables declared with
const
orlet
and Arrow Functions are NOT hoisted.Variables declared with
var
will be given the valueundefined
until their assignment statement is reached.Functions declared with
function
are fully invoke-able anywhere within their scope.
// Good — Uncaught ReferenceError: Cannot access 'name' before initialization
console.log(`Hi ${name}!`);
const name = 'Jane';
// Also Good — Uncaught ReferenceError: Cannot access 'age' before initialization
console.log(`I'm ${age}.`);
let age = 101;
// Bad! — Prints "Hi, undefined?" with no Error
console.log(`Hi, ${weird}?`);
var weird = 'Tom';
// Confusing! — Throws an error but only because `undefined` doesn't have a `toUpperCase` method
console.log(str.toUpperCase());
var str = 'Some string';
// Bad! - This works but it really shouldn't
foo();
function foo() {
console.log('foo!');
}
Last updated