Web Technology IUnit 514 min read
JavaScript Basics: Data Types, Variables, Functions & Real-World Logic
Unit 5 of Web Technology I covers JavaScript’s core building blocks—primitive and non-primitive data types, variable declaration, scoping rules, function syntax, and parameter handling—with hands-on validation examples (like eSewa’s form checks) and comparisons to HTML/CSS workflows.
TAKEAWAYS:
- JavaScript has 8 primitive data types (6 + 2 special cases) and 1 non-primitive type (objects), each with unique storage/behavior.
- Variables use
let,const, orvar—scope rules determine accessibility (global vs. block), and hoisting affects execution order. - Functions are first-class citizens: they can be passed as arguments, returned from other functions, and assigned to variables.
- Client-side validation (e.g., phone/email checks) relies on type coercion, regex, and conditional logic—critical for apps like Daraz or Ncell.
- Debugging tools (Chrome DevTools) let you inspect variables, call stacks, and event listeners in real time.
- Real-world tie-ins: WhatsApp’s message encryption uses string/boolean logic; YouTube’s “Recommended” system leverages object properties and array methods.
Core Concepts: Data Types in JavaScript
JavaScript’s data types are the foundation of all logic. They determine how values are stored, compared, and manipulated. The language categorizes them into primitive (immutable, stored by value) and non-primitive (mutable, stored by reference).
1. Primitive Data Types
JavaScript has 6 core primitives plus 2 special cases (often treated as primitives for simplicity):
mindmap
root((JavaScript Data Types))
Primitive
Number
Examples: 42, 3.14, -0.5
Notes: Includes integers, floats, and special values like `Infinity`, `NaN`
String
Examples: "hello", 'Nepal', `` `template ${strings}` ``
Notes: Immutable sequences of Unicode characters
Boolean
Examples: `true`, `false`
Notes: Used in conditions and logical operations
Null
Example: `null`
Notes: Represents "no value" or "empty"
Undefined
Example: `undefined`
Notes: Default value of uninitialized variables
Symbol
Example: `Symbol('id')`
Notes: Unique and immutable (ES6+), used as object property keys
Special Cases
BigInt
Example: `123n` (note the `n` suffix)
Notes: Handles integers larger than `Number`’s safe range (2^53 - 1)
Object
Example: `{name: "Ramesh", age: 25}`
Notes: **Non-primitive**; mutable key-value collectionsWhy it matters:
- Type coercion happens automatically (e.g.,
"5" + 2becomes"52"), but explicit checks (typeof) prevent bugs. nullvs.undefined:nullis intentional absence;undefinedis default or missing.
| Type | Example | Mutable? | Storage | Key Use Cases |
|---|---|---|---|---|
| Number | 42, 3.14 |
No | 64-bit float | Math operations, counters |
| String | "hello" |
No | UTF-16 | Text display, user input |
| Boolean | true |
No | 1 bit | Conditions (if, loops) |
| Null | null |
No | — | Reset variables, API responses |
| Undefined | undefined |
No | — | Uninitialized vars, function returns |
| Symbol | Symbol('id') |
No | Unique ID | Object property keys (avoid collisions) |
| BigInt | 123n |
No | Arbitrary | Cryptography, large IDs |
| Object | {} |
Yes | Reference | Complex data (arrays, functions, DOM) |
2. Variables: Declaration and Scope
Variables store data temporarily. JavaScript offers three ways to declare them, each with different scoping rules:
stateDiagram-v2
[*] --> VarDeclared
VarDeclared --> GlobalScope: if outside function/block
VarDeclared --> FunctionScope: if inside function (old behavior)
GlobalScope --> Hoisted: accessible anywhere
FunctionScope --> Hoisted: accessible in function
[*] --> LetConstDeclared
LetConstDeclared --> BlockScope: if inside { }
BlockScope --> NotHoisted: TDZ (Temporal Dead Zone) until declaration
BlockScope --> GlobalScope: if outside any blockKey Rules:
var:- Function-scoped (or global if declared outside functions).
- Hoisted: Declared at the top of its scope, initialized with
undefined. - Problem: Redeclaration allowed → bugs in loops.
let:- Block-scoped (e.g., inside
{}). - Not hoisted: Throws
ReferenceErrorif accessed before declaration (Temporal Dead Zone). - Can be redeclared in a new block.
- Block-scoped (e.g., inside
const:- Block-scoped.
- Must be initialized at declaration.
- Cannot be reassigned (but object/array properties can change).
Worked Example: Scope in Action
function exampleScope() {
if (true) {
var x = 10; // Function-scoped (leaks outside if-block)
let y = 20; // Block-scoped (dies here)
const z = 30; // Block-scoped
}
console.log(x); // 10 (works)
console.log(y); // ReferenceError (y is not defined)
console.log(z); // ReferenceError (z is not defined)
}
exampleScope();
Real-World Tie-In: eSewa’s User Session
eSewa stores user session data in block-scoped const variables to prevent accidental overwrites. For example:
const userSession = {
userId: "USER123",
balance: 5000,
isLoggedIn: true
};
// Later, when updating balance:
userSession.balance = 4800; // Allowed (property change)
userSession = null; // TypeError (reassignment blocked)
3. Functions: The Workhorses of JavaScript
Functions are reusable blocks of code that perform tasks. They can:
- Take parameters (inputs).
- Return a value (or
undefined). - Be nested, anonymous, or arrow functions.
Function Syntax
// Declaration (hoisted)
function greet(name) {
return `Hello, ${name}!`;
}
// Expression (not hoisted)
const greet = function(name) {
return `Hello, ${name}!`;
};
// Arrow function (ES6+)
const greet = (name) => `Hello, ${name}!`;
Parameters vs. Arguments
- Parameters: Variables listed in the function definition (e.g.,
function add(a, b)). - Arguments: Actual values passed when calling the function (e.g.,
add(2, 3)).
Default Parameters (ES6):
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
greet(); // "Hello, Guest!"
Rest Parameters:
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3); // 6
Caption: Debugging a nested function call in Pathao’s order-processing script.
4. Type Coercion and Explicit Checks
JavaScript automatically converts types in certain operations (e.g., + for strings/numbers). This can lead to unexpected results:
flowchart TD A["Operation: '5' + 2"] --> B["Step 1: String Coercion"] B --> C["5" + "2" = "52"] D["Operation: 5 == '5'"] --> E["Step 1: String Coercion"] E --> F["Step 2: Number Comparison"] F --> G["5 == 5 → true"] H["Operation: 5 === '5'"] --> I["Step 1: Strict Check"] I --> J["Types differ → false"]
Best Practices:
- Use strict equality (
===) to avoid coercion. - Use
typeofto check types explicitly:typeof 42; // "number" typeof "hello"; // "string" typeof null; // "object" (historical bug!)
Worked Example: Phone Number Validation
function validatePhone(phone) {
// Check if input is a string and matches 10-digit pattern
return typeof phone === "string" &&
/^\d{10}$/.test(phone);
}
validatePhone("9800123456"); // true
validatePhone("98001234"); // false
Real-World Use: Ncell’s IVR system uses regex to validate phone inputs before processing calls.
5. Common Pitfalls and Debugging
Hoisting:
console.log(age); // undefined (var is hoisted) var age = 25;Fix: Always declare variables at the top of their scope or use
let/const.==vs.===:0 == false; // true (coercion) 0 === false; // false (strict)Mutable Objects:
let obj = { a: 1 }; function modify(o) { o.a = 2; } modify(obj); console.log(obj.a); // 2 (objects are passed by reference)Debugging with Chrome DevTools:
- Console: Log variables (
console.log(varName)). - Sources Panel: Step through code line-by-line.
- Call Stack: See nested function calls (e.g., in Daraz’s checkout flow).
- Console: Log variables (
Caption: Tracing a function call in a WhatsApp Web message-sending script.
In the Real World
JavaScript’s data types and functions power the logic behind apps Nepal’s students use daily:
eSewa’s Payment Validation
- Idea Used: Type checking + regex for phone/email validation.
- How: Before processing a payment, eSewa checks:
if (typeof phone === "string" && /^\d{10}$/.test(phone)) { proceedToPayment(); } - Why: Prevents fraud by ensuring inputs match expected formats.
Khalti’s Transaction Logging
- Idea Used: Objects and arrays to store transaction data.
- How: Each transaction is an object in an array:
const transactions = [ { id: "TXN001", amount: 500, status: "completed" }, { id: "TXN002", amount: 2000, status: "pending" } ]; - Why: Enables filtering (e.g.,
transactions.filter(t => t.status === "completed")).
Pathao’s Order Queue
- Idea Used: Functions and closures to manage rider assignments.
- How: Pathao uses a function to assign the nearest rider:
function assignRider(orders) { return orders.sort((a, b) => a.distance - b.distance)[0]; } - Why: Ensures efficient routing by leveraging array methods and comparisons.
NEPSE Stock Price Updates
- Idea Used: Asynchronous functions (covered later) to fetch real-time data.
- How: NEPSE’s website uses
fetch()to get stock prices:async function getStockPrice(symbol) { const response = await fetch(`/api/stock/${symbol}`); return response.json(); } - Why: Prevents UI freezing while waiting for server responses.
WhatsApp’s Message Encryption
- Idea Used: Boolean logic for encryption flags.
- How: Messages are marked as encrypted with:
const isEncrypted = true; if (isEncrypted) { applyAES256Cipher(message); } - Why: Ensures end-to-end security using simple but critical type checks.
Worked Example: Daraz Order Processing
Scenario: Daraz needs to validate an order before processing it. The order has:
- A user ID (must be a number).
- A phone number (must be a 10-digit string).
- A password (must be at least 8 characters with a number).
Solution:
function validateOrder(userId, phone, password) {
// Check userId is a number
if (typeof userId !== "number" || isNaN(userId)) {
return "Invalid user ID";
}
// Check phone is 10-digit string
if (typeof phone !== "string" || !/^\d{10}$/.test(phone)) {
return "Invalid phone number";
}
// Check password meets criteria
if (typeof password !== "string" ||
password.length < 8 ||
!/\d/.test(password)) {
return "Password too weak";
}
return "Order valid!";
}
// Test cases
validateOrder(12345, "9800123456", "secure123"); // "Order valid!"
validateOrder("abc", "9800123", "weak"); // "Invalid user ID"
Visualization of Validation Flow:
flowchart TD
A["Start"] --> B{"User ID Valid?"}
B -->|"No"| C["Return 'Invalid user ID'"]
B -->|"Yes"| D{"Phone Valid?"}
D -->|"No"| E["Return 'Invalid phone'"]
D -->|"Yes"| F{"Password Valid?"}
F -->|"No"| G["Return 'Weak password'"]
F -->|"Yes"| H["Return 'Order valid!'"]Comparison: JavaScript vs. Other Languages
| Feature | JavaScript | Python | Java |
|---|---|---|---|
| Variable Declaration | let, const, var |
var (dynamic typing) |
final, static |
| Type Checking | Dynamic (coercion) | Dynamic | Static (compiled) |
| Function Scope | Block/Function | Block/Module | Block/Method |
| Hoisting | var hoisted |
No hoisting | No hoisting |
| Default Parameters | Supported (ES6) | Supported | Supported (Java 8+) |
| Closures | First-class | First-class | Limited (lambdas) |
Exam Tip: How to Score Full Marks
Data Types:
- Must-know: List all 8 primitives +
BigInt/Object. Explain mutability and storage differences. - Common mistake: Forgetting
Symbolor confusingnull/undefined. - Exam trick: If asked to "discuss," use a comparison table (like above) with 3–4 key columns.
- Must-know: List all 8 primitives +
Variables:
- Focus on scope: Draw a scope diagram (like the
stateDiagram-v2above) forvarvs.let/const. - Practical tip: Always use
constby default unless reassignment is needed.
- Focus on scope: Draw a scope diagram (like the
Functions:
- Syntax: Know declaration, expression, and arrow functions. Show one example of each.
- Parameters: Explain rest parameters (
...args) and default values. - Real-world link: Relate to form validation (e.g., "Write a function to validate an email").
Type Coercion:
- Key point:
==coerces;===does not. Show 3 examples (e.g.,0 == false,"5" + 2). - Debugging: Mention
typeofand how to avoid coercion bugs.
- Key point:
Worked Examples:
- Structure: Input → Logic → Output → Edge Cases.
- Real-world tie-in: Always link to a Nepali app (e.g., "This is how eSewa checks phone numbers").
- Visual aid: Use flowcharts or tables to organize logic.
Sample Exam Question Breakdown: Question: "Write a JavaScript program to take two integers and find their sum if both are even; otherwise, find their difference." Full-Mark Answer:
function evenOddSumDiff(a, b) {
// Check if both are even
if (Number.isInteger(a) && Number.isInteger(b) &&
a % 2 === 0 && b % 2 === 0) {
return a + b; // Sum if both even
} else {
return Math.abs(a - b); // Difference otherwise
}
}
// Test cases
console.log(evenOddSumDiff(4, 6)); // 10 (4+6)
console.log(evenOddSumDiff(3, 5)); // 2 (5-3)
console.log(evenOddSumDiff(2, 3)); // 1 (3-2)
Why this scores full marks:
- Input validation: Checks
Number.isInteger. - Logic: Clear
if-elsewith comments. - Edge cases: Includes odd/even combinations.
- Output: Uses
Math.absfor consistent results.
Final Reminder:
- Visuals > Text: Always draw diagrams for scope, functions, or validation flows.
- Real-world links: Exams often ask for applications—be ready to tie concepts to eSewa, Daraz, or Ncell.
- Debugging: Mention tools like Chrome DevTools to show practical skills.
Based on the TU BITM syllabus for Web Technology I (IT237), unit 5.
Discussion
Loading…