Understanding Variables and Data Types in Javascript [Injustice League edition]
Table of contents
- Variables
- Data Types
- Primitive Data Type
- Non-Primitive (Reference) Data
- Type-checking data types
- Fun Fact: All javascript values except primitive data types are technically an object!!!
- Type Conversion
- 1. String() → Converts to a String
- 2. Number() → Converts to a Number
- 3. Boolean() → Converts to a Boolean
- 4. parseInt() → Converts to an Integer
- 5. parseFloat() → Converts to a Floating-Point Number
“Imagine a world where human beings pray to an alien God... an alien who was just a regular being on their planet, Kryptonite. I must stop the Justice League and everybody in it to regain the power and respect we humans deserve,” said Lex Luthor, sitting alone in his chair, contemplating the formation of an Injustice league.
Lex wants to form a squad capable of overpowering the Justice League and, with it, Superman, with the help of Javascript.
Variables
Variables are containers to store data. In Lex’s case, to form a league of villains and supervillains. He researches variables to store the capable villains and supervillains in them. There are three types of variables: let, var and const.
let
We use let for variables that might change its value.
Block-scoped: Only accessible within the block
{}
where it’s declared.let a = 100; if (true) { let a = 200; // This a is only inside the block console.log(a); // Output: 200 } console.log(a); // Output: 100 (original a is not affected)
Mutable Variable (can be re-assigned): You can change its value after declaration
let y = 30; y = 40; // ✅ Allowed
Cannot be redeclared – You cannot declare the same variable again in the same scope.
let x = 10; let x = 20; // ❌ Error: Identifier 'x' has already been declared
Hoisting:
let
is hoisted but remains uninitialized, meaning it cannot be accessed before its declaration. Attempting to use it before declaration results in aReferenceError
because it’s in the ‘Temporal Dead Zone’ (TDZ).console.log(z); // ❌ ReferenceError let z = 50;
Const
We use const when the variable’s value does not change after declaration.
Block-scoped: Only accessible within the block
{}
where it’s declared.const a = 100; if (true) { const a = 200; // This a is only inside the block console.log(a); // Output: 200 } console.log(a); // Output: 100 (original a is not affected)
Immutable Variable (cannot be re-assigned): The value cannot change once assigned.
const y = 30; y = 40; // ❌ Error: Assignment to constant variable
Cannot be redeclared: You cannot declare the same variable name in the same scope.
const x = 10; const x = 20; // ❌ Error: Identifier 'x' has already been declared
Hoisting:
const
is hoisted but remains uninitialized, meaning it cannot be accessed before its declaration. Attempting to use it before declaration results in aReferenceError
because it’s in the ‘Temporal Dead Zone’ (TDZ).console.log(z); // ❌ ReferenceError const z = 50;
Var
🚫 Avoid var
in modern JavaScript to prevent unexpected behaviour and hard-to-debug issues.
Function-scoped – Variables declared with
var
are accessible throughout the function, not just inside a block{}
.function example() { var x = 10; if (true) { var y = 20; // ✅ Accessible throughout the function } console.log(y); // ✅ Works } console.log(x); // ❌ Error: x is not defined (function scope)
Mutable variable (can be re-assigned) – You can change its value after declaration. 👍🏻
var b = 30; b = 40; // ✅ Allowed console.log(b); // Output: 40
Can be redeclared – You can declare the same variable multiple times without errors. 👍🏻
var a = 10; var a = 20; // ✅ No error console.log(a); // Output: 20
Hoisting –
var
is hoisted to the top of its scope but initialized asundefined
.console.log(c); // ✅ Output: undefined (hoisting) var c = 50;
Hence, to summarize:
Feature | var | let | const |
Scoping | Function-scoped ✅ | Block-scoped ✅ | Block-scoped ✅ |
Accessible Outside Block? | ✅ Yes (if inside a function) | ❌ No | ❌ No |
Mutable (Can Be Re-assigned)? | ✅ Yes | ✅ Yes | ❌ No (Immutable) |
Can Be Redeclared? | ✅ Yes | ❌ No | ❌ No |
Hoisted? | ✅ Yes (initialized as undefined ) | ✅ Yes (but in TDZ) | ✅ Yes (but in TDZ) |
Initialization Required? | ❌ No | ❌ No | ✅ Yes |
Best Use Case | 🚫 Avoid using var | Use when reassignment is needed | Use for constants or fixed values |
Best practices for using variables:
Follow camelCase for naming (
myVariableName
).Declare variables before using them to avoid hoisting-related bugs.
Variable Naming Rules
Must start with a letter (
a-z
,A-Z
), underscore (_
), or dollar sign ($
).Cannot start with a number.
Can contain letters, digits, underscores, and dollar signs.
Case-sensitive (
myVar
andMyVar
are different).Cannot use reserved keywords (
let
,if
,function
, etc.).Should be descriptive (e.g.,
userName
instead ofx
).
Finally, Lex decides to make variables using let for villains (B-Listers, e.g. Toy Man) and const for supervillains (A-Listers, e.g. Joker).
let villains;
const supervillains;
Data Types
Data types define the kind of values that variables can store and manipulate. JavaScript is a dynamically typed language, meaning variables do not have a fixed type and can hold different types of values at different times.
JavaScript has two categories of data types:
Primitive Data Types (Immutable, stored directly in memory)
Non-Primitive (Reference) Data Types (Mutable, stored by reference)
Primitive Data Type
Primitive data types hold simple values and are immutable.
String
: Represents textual data.let name = "Lex";
Number
: Represents both integer and floating-point numbers.let age = 35; let height = 1.80;
BigInt
: Used for very large numbers beyondNumber
limit.let lexAlienClones = 9007199254740991n;
Boolean
: Representstrue
orfalse
values.let lexIsSupervillan = true;
undefined
: A variable that has been declared but not assigned a value.let lex; console.log(lex); // undefined
null
: Represents an empty or unknown value.let lexFlaw = null;
symbol
: Unique and immutable identifier.let lexId = Symbol("unique");
Non-Primitive (Reference) Data
Reference data types store memory addresses rather than actual values.
object
: They are containers for properties and methods where properties are named values and methods are functions stored as properties.let villian = { name: "Joker", age: 35 };
array
: Indexed collection of values.let numbers = [1, 2, 3, 4, 5];
function
: A callable block of code.function greet() { return "Hello! Join Injustice League"; }
To summarize some fundamental differences between the two data types:
Feature | Primitive Data Type | Reference Data Type |
Storage | Stored directly in memory (stack) | Stored by reference (heap) |
Mutability | Immutable (cannot change) | Mutable (can change) |
Comparison | Compared by value | Compared by reference |
Lex decides to use an array as a data type for his purpose and makes two arrays with the variables defined before.
let villains = ["Black Manta", "The Riddler", "Cheetah", "Captain Cold", "Clayface"]
const supervillains = ["The Joker", "Lex Luthor", "Darkseid", "Deathstroke", "Reverse-Flash"];
Type-checking data types
Use the typeof
operator to check the data type:
console.log(typeof 42); // "number"
console.log(typeof "Hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof null); // "object" (⚠️ Historical bug)
console.log(typeof undefined); // "undefined"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
Fun Fact: All javascript values except primitive data types are technically an object!!!
Type | typeof Result | Reason It’s an Object |
null | "object" | This is a historical bug in JavaScript. null is not actually an object, but due to an early implementation issue, typeof null incorrectly returns "object" . The correct way to check for null is by using value === null . |
array | "object" | Arrays are a special type of object in JavaScript. They use indexed keys (0,1,2,...) instead of named properties, and they inherit from Array.prototype , which provides methods like .push() , .map() , and .filter() . Despite being an object, you should check if a value is an array using Array.isArray(value) . |
function | "function" | Functions inherit from Function.prototype , meaning they can have properties and methods just like regular objects. However, JavaScript gives them a unique typeof result ("function" ) to distinguish them from other objects. |
Type Conversion
Implicit type conversion
JavaScript automatically converts types in some cases.
console.log("5" + 3); // "53" (string concatenation) console.log("5" - 3); // 2 (numeric conversion) console.log(true + 1); // 2 (true → 1) console.log(false + 1); // 1 (false → 0) console.log("t" + "t"); // tt console.log("3" + "4"); // 34 console.log("t" - "t"); // NaN (Not a number) console.log("t" - 1); // NaN (Not a number)
Explicit type conversion (Type Casting)
Manually convert data types using built-in methods such as
String()
,Number()
,Boolean()
,parseInt()
,parseFloat()
.1.
String()
→ Converts to a Stringlet num = 123; console.log(String(num)); // "123" (Number → String) console.log(String(true)); // "true" (Boolean → String) console.log(String(null)); // "null" (null → String)
2.
Number()
→ Converts to a Numberlet str = "42"; console.log(Number(str)); // 42 (String → Number) console.log(Number("abc")); // NaN (Cannot convert "abc" to a number) console.log(Number(true)); // 1 (Boolean → Number) console.log(Number(false)); // 0 (Boolean → Number)
3.
Boolean()
→ Converts to a Booleanconsole.log(Boolean(1)); // true (1 is truthy) console.log(Boolean(0)); // false (0 is falsy) console.log(Boolean("hello")); // true (Non-empty string is truthy) console.log(Boolean("")); // false (Empty string is falsy) console.log(Boolean(null)); // false (null is falsy)
4.
parseInt()
→ Converts to an Integerconsole.log(parseInt("42px")); // 42 (Extracts number from a string) console.log(parseInt("3.14")); // 3 (Removes decimal part) console.log(parseInt("abc")); // NaN (Cannot extract number)
5.
parseFloat()
→ Converts to a Floating-Point Numberconsole.log(parseFloat("3.14px")); // 3.14 (Extracts float from a string) console.log(parseFloat("42")); // 42 (Still returns a number) console.log(parseFloat("abc")); // NaN (Cannot extract number)
Hence, by understanding and using variables and data types, Lex Luthor can formulate a league of villains at his disposal who have the potential to cause havoc not only on Earth but also on an intergalactic level.