DEV Community

Cover image for #001: Unlocking Variables & The Flavors of Data in JavaScript πŸ”‘πŸ¦
Harshit Savani
Harshit Savani

Posted on • Edited on

#001: Unlocking Variables & The Flavors of Data in JavaScript πŸ”‘πŸ¦

Alright, Dev.to community! Let's dive headfirst into the very first foundational block of JavaScript (and indeed, almost any programming language): Variables and Data Types.

If you're already familiar with these, fantastic! Consider this a quick refresher, or maybe you'll pick up a nuanced detail (or a famous JS quirk!) you hadn't considered before. If you're brand new, welcome aboard – this is where all the magic begins!


Variables - Your Data's Little Home 🏑

Imagine you're organizing your kitchen, and you have different ingredients. Instead of just scattering them everywhere, you put them into labeled containers. In programming, variables are those labeled containers. They are named storage locations that hold values (our ingredients).

// Think of 'myName' as a box labeled "My Name"
// And inside, we put the value "Harry"
let myName = "Harry";

// Now, 'userAge' is a box labeled "User Age"
// holding the number 30
let userAge = 30;
Enter fullscreen mode Exit fullscreen mode

Why do we need them? So we can store information, refer to it later by a simple name, and even change that information!

Declaring Variables: The var, let, and const Story

JavaScript gives us a few keywords to declare our variables. Understanding their differences is crucial.

var (The Old-School, Sometimes Troublesome Relative):

var was the original way to declare variables. While still functional, it has some quirks (like function-scoping and hoisting behaviors that can lead to confusion and bugs) that led to the introduction of let and const. You'll still see it in older codebases, but generally, we avoid it for new development.

let (The Flexible Friend):

Introduced in ES6 (ECMAScript 2015), let is your go-to for variables whose values you expect to change. It's block-scoped, meaning it only exists within the curly braces {} where it's defined.

let score = 0; // Declared and initialized
console.log(score); // Output: 0

score = 100; // Value can be reassigned
console.log(score); // Output: 100

if (true) {
  let message = "Hello from inside the block!";
  console.log(message); // Output: "Hello from inside the block!"
}
// console.log(message); // ReferenceError: message is not defined (outside the block)
Enter fullscreen mode Exit fullscreen mode

const (The Steady Sentinel):

Also introduced in ES6, const is for constants. Once you assign a value to a const variable, you cannot reassign it. Like let, it's also block-scoped. const is often preferred when you know a variable's value won't change, as it prevents accidental reassignments and makes your code more predictable.

const PI = 3.14159; // Declared and initialized
console.log(PI); // Output: 3.14159

// PI = 3.0; // TypeError: Assignment to constant variable. (This will throw an error!)

const appName = "My Awesome App";
// appName = "New App"; // Nope!
Enter fullscreen mode Exit fullscreen mode

A quick note on const and objects/arrays: While you can't reassign the variable itself, you can modify the contents of an object or array declared with const. More on this when we talk about reference types!

Naming Conventions: Keep it Clean!

  • Camel Case: The standard in JavaScript. Start with a lowercase letter, and then capitalize the first letter of each subsequent word (firstName, numberOfUsers).
  • Descriptive Names: isLoggedIn is better than x. getUserData is better than getData.
  • Avoid Reserved Keywords: Don't use words JavaScript already uses (function, if, for, let, const, etc.).

Data Types - The Flavors of Information 🍦

Just like your kitchen ingredients come in different forms (solids, liquids, spices), the values our variables hold also come in different data types. JavaScript is a dynamically typed language, meaning you don't have to explicitly tell it what type of data a variable will hold (it figures it out on the fly).

To check the type of a variable, we can use the handy typeof operator:

let myFavNumber = 7;
console.log(typeof myFavNumber); // Output: "number"

let greeting = "Hello, world!";
console.log(typeof greeting); // Output: "string"
Enter fullscreen mode Exit fullscreen mode

Let's explore the main types!

Primitive Data Types (The Building Blocks)

These are the simplest forms of data, representing single, immutable values.

  • String: Represents textual data (words, sentences, characters). Enclosed in single quotes (''), double quotes (""), or backticks. Backticks are great for template literals where you can embed expressions easily!
let productName = 'Laptop';
let message = "Product: " + productName;
let welcome = `Welcome, ${myName}!`; // Using template literal with backticks

console.log(typeof productName); // "string"
console.log(welcome); // "Welcome, Harry!"
Enter fullscreen mode Exit fullscreen mode
  • Number: Represents both integers (whole numbers) and floating-point numbers (decimals). JavaScript handles all numbers as floating-point internally. Also includes special values like Infinity and NaN (Not-a-Number).
let price = 99.99;
let quantity = 5;
let bigNum = 100 / 0; // Infinity
let notANum = "hello" * 2; // NaN

console.log(typeof price); // "number"
console.log(bigNum); // Infinity
console.log(notANum); // NaN
Enter fullscreen mode Exit fullscreen mode
  • Boolean: Represents a logical entity and can only have one of two values: true or false. Used for conditional logic.
let carModel; // Declared, but no value assigned
console.log(carModel); // undefined
console.log(typeof carModel); // "undefined"
Enter fullscreen mode Exit fullscreen mode
  • Symbol: (Introduced in ES6) Represents a unique identifier. Every time you create a Symbol, it's guaranteed to be unique, even if it has the same description. Used for unique property keys. Don't worry too much about this one for absolute beginners, just know it exists!
const id1 = Symbol('id');
const id2 = Symbol('id');

console.log(id1 === id2); // false (they are unique!)
console.log(typeof id1); // "symbol"
Enter fullscreen mode Exit fullscreen mode
  • BigInt: (Newer addition) Represents integers with arbitrary precision. Used for numbers larger than 2^53 - 1 (the maximum for a regular Number). You add an n suffix to a number to make it a BigInt.
const reallyBigNum = 9007199254740991n + 1n;
console.log(reallyBigNum); // 9007199254740992n
console.log(typeof reallyBigNum); // "bigint"
Enter fullscreen mode Exit fullscreen mode
  • Null (The "Intentionally Empty" Primitive) This brings us to a crucial primitive type: null. Unlike undefined (which means "not yet assigned a value"), null means "there is no value here, and I've explicitly set it to be empty." It's often used to indicate the absence of an object.
let response = null; // We intentionally set it to nothing
console.log(response); // null
console.log(typeof response); // Hold on... what?!
Enter fullscreen mode Exit fullscreen mode

The "Aha!" Moment: Why typeof null === 'object'? 🀯

If you just ran that last typeof response, you probably saw:

object
Enter fullscreen mode Exit fullscreen mode

...and if you're like me, your eyebrows might have shot up your forehead. "Wait," you think, "null is a primitive, it means 'nothing,' why on Earth does JavaScript tell me it's an object?!"

Welcome to one of JavaScript's oldest, most famous (and slightly embarrassing) quirks!

The Backstory of a Bug (It's a Feature Now, Kind Of!)

This isn't a feature; it's a bug! It dates back to the very first version of JavaScript. In that initial implementation, values were stored with a type tag and the actual value. For objects, the type tag was 0. null was represented as the NULL pointer, which in low-level terms, was all zeroes. When the typeof operator was implemented, it simply checked the type tag. Since null had the same type tag as objects (0), typeof null erroneously returned 'object'.

Why Can't They Fix It?

It's been acknowledged as a bug for decades. However, fixing it now would break an unimaginable amount of existing code on the web. Imagine countless websites relying on typeof myVar === 'object' to check if something isn't null (because they assume if it's an object, it's not null). Changing this behavior would unleash chaos!


Non-Primitive (Reference) Data Types - The Complex Cousins πŸ§±πŸ”—

Unlike primitives, non-primitive data types (also called reference types) can hold collections of data and more complex entities. When you assign a non-primitive value to a variable, you're not storing the actual value in that variable's box. Instead, you're storing a reference (like an address) to where that data lives in memory.

This has important implications for how they behave when copied or compared!

  • Object: The most fundamental non-primitive type. Everything else (arrays, functions, dates, etc.) in JavaScript is essentially an object or behaves like one. Objects are collections of key-value pairs.
let user = {
  firstName: "Jane",
  lastName: "Doe",
  age: 28,
  isStudent: false
};

console.log(typeof user); // "object"
console.log(user.firstName); // "Jane"
Enter fullscreen mode Exit fullscreen mode
  • Array: A special type of object used for ordered lists of data. Elements in an array are accessed by their numerical index (starting from 0).
let colors = ["red", "green", "blue"];
let mixedBag = [1, "hello", true, { id: 1 }]; // Arrays can hold different types!

console.log(typeof colors); // "object" (Yep, arrays are objects!)
console.log(colors[0]); // "red"
Enter fullscreen mode Exit fullscreen mode
  • Function: Functions are blocks of code designed to perform a particular task. In JavaScript, functions are also a special type of object. They can be stored in variables, passed as arguments, and returned from other functions.
function greet(name) {
  return `Hello, ${name}!`;
}

console.log(typeof greet); // "function" (a special object subtype)
let greetingMessage = greet("Dev.to Reader");
console.log(greetingMessage); // "Hello, Dev.to Reader!"
Enter fullscreen mode Exit fullscreen mode

(We'll dedicate a whole future post to functions, they're that important!)

The Reference Type Gotcha: Copying vs. Referencing

This is where understanding reference types is crucial:

let originalUser = { name: "Alice" };
let copiedUser = originalUser; // 'copiedUser' now holds a REFERENCE to the SAME object

copiedUser.name = "Bob"; // We change the name using 'copiedUser'

console.log(originalUser.name); // Output: "Bob" (Uh oh! 'originalUser' changed too!)
Enter fullscreen mode Exit fullscreen mode

Both originalUser and copiedUser point to the same object in memory. Modifying through one variable affects the data accessed by the other. To truly copy a non-primitive, you need to use techniques like the spread operator (...), Object.assign(), or structured cloning. But that's a topic for another day!


Conclusion: Foundations Are Everything! πŸ—οΈ

Phew! We've covered a lot: the basics of variables, the distinct primitive data types, the complex world of reference types, and we even debunked the typeof null mystery!

Understanding these fundamental concepts is like learning the alphabet and basic grammar of JavaScript. It might seem simple at first glance, but truly grasping their nuances (like the null quirk or how reference types behave) is what separates a good developer from someone who's constantly battling unforeseen side effects.

Next up, we'll crank up the intensity and dive into Operators and Comparisons, including why == can be both helpful and utterly chaotic! Get ready for another "Aha!" moment or two.

Over and Out!

Top comments (0)