JavaScript Zero to Advanced #2: Variables, Data Types & Operators
In Part 1 we set up our tools and printed our first messages. Now it is time to work with real data. Every program needs to remember values (a user's name, a cart total, whether someone is logged in) and combine them. That is what variables, data types and operators are for.
Declaring variables: let, const and var
A variable is a named box that holds a value. Modern JavaScript gives you two keywords to create one:
constfor values that will not be reassigned.letfor values that will change.
const name = "Budi"
let age = 25
console.log(name, age)
age = 26 // allowed: let can be reassigned
console.log(name, age)
try {
name = "Siti" // not allowed: const cannot be reassigned
} catch (error) {
console.log(error.name + ": " + error.message)
}
Output:
Budi 25
Budi 26
TypeError: Assignment to constant variable.
A good default: use const everywhere, and switch to let only when you really need to reassign. This makes your code easier to read, because a reader knows a const never points to something else.
You will also see var in older code. It works, but it has confusing scoping rules (we will see why in Part 4). Avoid it in new code.
Naming rules
- Names can contain letters, digits,
_and$, but cannot start with a digit. - They are case-sensitive:
totalandTotalare different variables. - The convention is camelCase:
firstName,totalPrice,isLoggedIn.
Data types
JavaScript has seven primitive types and one structural type, object. You can check a value's type with the typeof operator:
console.log(typeof "hello") // string
console.log(typeof 42) // number
console.log(typeof 3.14) // number
console.log(typeof true) // boolean
console.log(typeof undefined) // undefined
console.log(typeof null) // "object" (a famous historical bug)
console.log(typeof 10n) // bigint
console.log(typeof Symbol("id")) // symbol
console.log(typeof { a: 1 }) // object
console.log(typeof [1, 2, 3]) // object (arrays are objects)
Output:
string
number
number
boolean
undefined
object
bigint
symbol
object
object
| Type | Example | Notes |
|---|---|---|
| string | "Siti", 'hi' | Text, in single, double or back quotes |
| number | 42, -3.5, NaN | Integers and decimals share one type |
| boolean | true, false | Yes/no values |
| undefined | undefined | "No value assigned yet" |
| null | null | "Intentionally empty" |
| bigint | 9007199254740993n | Very large integers |
| symbol | Symbol("id") | Unique identifiers (advanced) |
Objects and arrays get their own parts later in the series. For now, focus on strings, numbers and booleans.
Working with strings
Strings can be joined with +, but the modern way is a template literal: wrap the text in backticks and insert values with ${...}:
const firstName = "Siti"
const city = "Bandung"
const items = 3
console.log("Hi " + firstName + " from " + city)
console.log(`Hi ${firstName} from ${city}`)
console.log(`You have ${items} items, total: ${items * 15000}`)
const message = "JavaScript"
console.log(message.length)
console.log(message.toUpperCase())
console.log(message.slice(0, 4))
console.log(message.includes("Script"))
Output:
Hi Siti from Bandung
Hi Siti from Bandung
You have 3 items, total: 45000
10
JAVASCRIPT
Java
true
Template literals can contain any expression inside ${}, including math, and they can span multiple lines. String methods like toUpperCase() never change the original string; they return a new one.
Numbers and arithmetic operators
const a = 17
const b = 5
console.log(a + b) // addition
console.log(a - b) // subtraction
console.log(a * b) // multiplication
console.log(a / b) // division
console.log(a % b) // remainder (modulo)
console.log(a ** 2) // exponent
let counter = 10
counter += 5 // same as counter = counter + 5
counter++ // add 1
console.log(counter)
console.log(0.1 + 0.2)
console.log((0.1 + 0.2).toFixed(2))
console.log(10 / 0, "abc" * 2)
Output:
22
12
85
3.4
2
289
16
0.30000000000000004
0.30
Infinity NaN
Two things surprise beginners here. First, 0.1 + 0.2 is not exactly 0.3 because numbers are stored in binary floating point (this happens in most languages). Use toFixed for display, or work in whole units such as cents. Second, invalid math does not crash: it gives Infinity or NaN ("Not a Number").
Type conversion and coercion
JavaScript will automatically convert types when you mix them. This is called coercion, and it is the source of many bugs:
console.log("5" + 2) // + with a string joins text
console.log("5" - 2) // - converts to number
console.log("5" * "2")
console.log(true + 1)
// Explicit conversion is clearer
console.log(Number("42") + 8)
console.log(parseInt("100px"))
console.log(parseFloat("3.75 kg"))
console.log(String(99) + 1)
console.log(Number("hello"))
Output:
52
3
10
2
50
100
3.75
991
NaN
Values from forms, URLs and prompt() are always strings. Convert them with Number(), parseInt() or parseFloat() before doing math.
Comparison and logical operators
Comparisons return a boolean. JavaScript has two kinds of equality:
console.log(5 == "5") // loose: converts types first
console.log(5 === "5") // strict: type must match too
console.log(0 == false)
console.log(0 === false)
console.log(null == undefined)
console.log(null === undefined)
console.log(10 > 7, 10 <= 7, 3 !== 4)
Output:
true
false
true
false
true
false
true false true
Always use === and !==. Loose equality applies conversion rules that are hard to remember.
Logical operators combine booleans: && (and), || (or), and ! (not). There is also ??, the nullish coalescing operator, which provides a fallback only for null or undefined:
const isLoggedIn = true
const isAdmin = false
console.log(isLoggedIn && isAdmin)
console.log(isLoggedIn || isAdmin)
console.log(!isAdmin)
const stock = 0
console.log(stock || 10) // 0 is falsy, so || picks 10
console.log(stock ?? 10) // 0 is not null/undefined, so ?? keeps 0
let nickname
console.log(nickname ?? "Guest")
Output:
false
true
true
10
0
Guest
The difference between || and ?? matters when 0, "" or false are valid values. We will talk more about "truthy" and "falsy" values in Part 3.
Common mistakes
- Using
==instead of===."" == 0istrue, which is almost never what you want. - Adding strings from inputs.
"2" + "3"is"23", not5. Convert first. - Reassigning a
const. You get TypeError: Assignment to constant variable. Useletif the value must change. - Checking for
NaNwith===.NaN === NaNisfalse. UseNumber.isNaN(value). - Using a variable before declaring it. With
let/constthis throws a ReferenceError. Declare first, use later.
Exercise
Create a small shopping calculator. Declare const price = "45000" (a string, as if it came from a form) and let quantity = 3. Convert the price to a number, compute the total, add an 11% tax, and print a sentence with a template literal such as Total for 3 items: 149850. Then try printing price + quantity without conversion and explain the result.
Summary
- Use
constby default andletwhen reassigning; avoidvar. - The main primitive types are string, number, boolean, undefined and null; check them with
typeof. - Template literals with
${}are the cleanest way to build strings. - Watch out for coercion: convert explicitly and compare with
===. ??gives a fallback only fornull/undefined, while||falls back for any falsy value.
In Part 3 we will use these values to make decisions with conditionals and repeat work with loops.
Related articles
PostgreSQL Zero to Advanced #1: Introduction & Setup
Start the series by understanding what a relational database is, installing PostgreSQL locally, and getting comfortable with psql commands like \l, \c and \dt.
PHP Zero to Advanced #1: Introduction & Setup
Start your PHP journey: what PHP is, how to install PHP 8.2+, run the built-in development server, and write your very first script with echo.
Ruby on Rails Zero to Advanced #1: Ruby Basics
Start the Rails journey with the language underneath it: irb, variables, strings, puts vs p, and symbols explained with runnable examples.