Week 09: JavaScript Objects, JSON & AJAX
Unit III - Data Handling & API Communication
Working with data in modern JavaScript!
What You'll Learn
- JavaScript Objects & Prototypes
- JSON format and methods
- Fetch API for HTTP requests
- Promises and async/await
- Error handling in async code
Why This Matters
Modern web apps constantly communicate with servers to fetch and send data. Understanding JSON and async JavaScript is essential for building dynamic applications!
Press → or click Next to continue
JavaScript Objects
Objects are collections of key-value pairs - the foundation of data in JavaScript.
Creating Objects
// Object literal (most common)
const person = {
name: 'Alice',
age: 25,
email: 'alice@example.com'
};
// Constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
const bob = new Person('Bob', 30);
// Object.create()
const student = Object.create(person);
student.grade = 'A';
Accessing Properties
// Dot notation
console.log(person.name); // 'Alice'
// Bracket notation
console.log(person['age']); // 25
// Dynamic property access
const key = 'email';
console.log(person[key]); // 'alice@...'
// Check if property exists
'name' in person // true
person.hasOwnProperty('name') // true
// Delete property
delete person.email;
Object Shorthand (ES6+)
const name = 'Alice';
const age = 25;
const person = { name, age }; // Same as { name: name, age: age }
Object Methods
Objects can contain functions - called methods.
Defining Methods
const calculator = {
value: 0,
// Method shorthand (ES6)
add(n) {
this.value += n;
return this; // for chaining
},
subtract(n) {
this.value -= n;
return this;
},
// Traditional syntax
multiply: function(n) {
this.value *= n;
return this;
},
getValue() {
return this.value;
}
};
// Method chaining
calculator.add(10).subtract(3).multiply(2);
console.log(calculator.getValue()); // 14
The 'this' Keyword
const user = {
name: 'Alice',
greet() {
console.log(`Hi, I'm ${this.name}`);
}
};
user.greet(); // "Hi, I'm Alice"
// 'this' depends on how function is called
const greet = user.greet;
greet(); // "Hi, I'm undefined"
// Fix with bind
const boundGreet = user.greet.bind(user);
boundGreet(); // "Hi, I'm Alice"
// Arrow functions don't have own 'this'
const obj = {
name: 'Test',
arrow: () => console.log(this.name),
regular() { console.log(this.name); }
};
Prototypes & Inheritance
JavaScript uses prototypal inheritance - objects inherit from other objects.
Prototype Chain
const animal = {
eat() {
console.log('Eating...');
}
};
const dog = Object.create(animal);
dog.bark = function() {
console.log('Woof!');
};
dog.bark(); // 'Woof!'
dog.eat(); // 'Eating...' (inherited)
// Check prototype
Object.getPrototypeOf(dog) === animal // true
animal.isPrototypeOf(dog) // true
ES6 Classes (Syntactic Sugar)
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call parent constructor
this.breed = breed;
}
speak() {
console.log(`${this.name} barks!`);
}
}
const rex = new Dog('Rex', 'German Shepherd');
rex.speak(); // "Rex barks!"
Note: ES6 classes are just syntactic sugar over JavaScript's prototype-based inheritance.
What is JSON?
JavaScript Object Notation - A lightweight data interchange format.
JSON Syntax Rules
- Data in key-value pairs
- Keys MUST be double-quoted strings
- Values can be: strings, numbers, booleans, null, arrays, objects
- No trailing commas
- No comments allowed
- No functions or undefined
// Valid JSON
{
"name": "Alice",
"age": 25,
"isStudent": true,
"courses": ["Math", "Physics"],
"address": {
"city": "Chennai",
"zip": "600001"
},
"spouse": null
}
JSON vs JavaScript Object
// JavaScript Object
const jsObj = {
name: 'Alice', // unquoted key OK
'full-name': 'Alice',
greet() {}, // functions OK
value: undefined // undefined OK
};
// JSON (string format)
const json = `{
"name": "Alice",
"full-name": "Alice Smith"
}`;
// JSON must be a string!
// JavaScript objects are in memory
Common Mistakes:
- Using single quotes for keys
- Trailing commas
- Including functions
JSON Methods
Convert between JSON strings and JavaScript objects.
JSON.parse()
Convert JSON string to JavaScript object
const jsonString = `{
"name": "Alice",
"age": 25,
"hobbies": ["reading", "coding"]
}`;
const user = JSON.parse(jsonString);
console.log(user.name); // "Alice"
console.log(user.hobbies[0]); // "reading"
// With reviver function
const data = '{"date": "2024-01-15"}';
const obj = JSON.parse(data, (key, value) => {
if (key === 'date') {
return new Date(value);
}
return value;
});
JSON.stringify()
Convert JavaScript object to JSON string
const user = {
name: 'Alice',
age: 25,
password: 'secret' // sensitive!
};
// Basic stringify
const json = JSON.stringify(user);
// '{"name":"Alice","age":25,"password":"secret"}'
// Pretty print with indentation
const pretty = JSON.stringify(user, null, 2);
// Filter properties (replacer)
const safe = JSON.stringify(user, ['name', 'age']);
// '{"name":"Alice","age":25}'
// Custom replacer function
const filtered = JSON.stringify(user, (key, value) => {
if (key === 'password') return undefined;
return value;
});
Error Handling
try {
const data = JSON.parse('invalid json');
} catch (error) {
console.error('Parse error:', error.message);
}
Introduction to AJAX
Asynchronous JavaScript And XML - Communicate with servers without reloading the page.
What is AJAX?
- Send/receive data in the background
- Update parts of page without refresh
- Originally used XMLHttpRequest
- Modern approach: Fetch API
Common Use Cases
- Load content on scroll (infinite scroll)
- Form submission without page reload
- Auto-save drafts
- Search suggestions
- Chat applications
XMLHttpRequest (Old Way)
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data');
xhr.onload = function() {
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
console.log(data);
}
};
xhr.onerror = function() {
console.error('Request failed');
};
xhr.send();
Note: XMLHttpRequest is verbose and callback-based. Modern code uses the Fetch API instead!
Fetch API Basics
The modern way to make HTTP requests in JavaScript.
GET Request
// Basic fetch (returns Promise)
fetch('https://api.example.com/users')
.then(response => {
if (!response.ok) {
throw new Error('Network error');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
// Response methods
response.json() // Parse as JSON
response.text() // Get as text
response.blob() // Get as binary
response.headers // Access headers
response.status // HTTP status code
response.ok // true if 200-299
POST Request
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Alice',
email: 'alice@example.com'
})
})
.then(response => response.json())
.then(data => {
console.log('Created:', data);
})
.catch(error => {
console.error('Error:', error);
});
// Other methods: PUT, PATCH, DELETE
fetch(url, { method: 'DELETE' })
fetch(url, {
method: 'PUT',
body: JSON.stringify(updatedData)
})
Promises
A Promise represents a value that may be available now, later, or never.
Promise States
- Pending: Initial state, waiting
- Fulfilled: Operation completed successfully
- Rejected: Operation failed
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
// Async operation
setTimeout(() => {
const success = true;
if (success) {
resolve('Data loaded!');
} else {
reject(new Error('Failed to load'));
}
}, 1000);
});
// Using the Promise
myPromise
.then(result => console.log(result))
.catch(error => console.error(error));
Promise Chaining
fetch('/api/user/1')
.then(response => response.json())
.then(user => {
console.log(user.name);
return fetch(`/api/posts?userId=${user.id}`);
})
.then(response => response.json())
.then(posts => {
console.log('Posts:', posts);
})
.catch(error => {
// Catches ANY error in the chain
console.error('Error:', error);
})
.finally(() => {
// Always runs
console.log('Request completed');
});
Each .then() returns a new Promise, enabling chaining!
Async/Await
Syntactic sugar that makes Promises look like synchronous code.
Basic Syntax
// async function always returns a Promise
async function fetchUser(id) {
// await pauses until Promise resolves
const response = await fetch(`/api/users/${id}`);
const user = await response.json();
return user;
}
// Using async function
fetchUser(1)
.then(user => console.log(user));
// Or with IIFE
(async () => {
const user = await fetchUser(1);
console.log(user);
})();
Error Handling
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch failed:', error);
throw error; // Re-throw if needed
} finally {
console.log('Cleanup...');
}
}
// Sequential vs Parallel
async function loadAll() {
// Sequential (slow)
const a = await fetchA();
const b = await fetchB();
// Parallel (fast!)
const [a, b] = await Promise.all([
fetchA(), fetchB()
]);
}
Promise Utilities
Static methods on Promise for handling multiple promises.
Promise.all()
// Wait for ALL promises to resolve
// Fails fast - rejects if ANY fails
const urls = [
'/api/users',
'/api/posts',
'/api/comments'
];
const promises = urls.map(url => fetch(url));
Promise.all(promises)
.then(responses => {
return Promise.all(
responses.map(r => r.json())
);
})
.then(([users, posts, comments]) => {
console.log(users, posts, comments);
})
.catch(error => {
console.error('One request failed:', error);
});
Other Utilities
// Promise.allSettled() - Wait for all, never rejects
const results = await Promise.allSettled([
fetch('/api/a'),
fetch('/api/b')
]);
// [{status:'fulfilled', value:...}, {status:'rejected', reason:...}]
// Promise.race() - First to resolve/reject wins
const fastest = await Promise.race([
fetch('/api/server1'),
fetch('/api/server2')
]);
// Promise.any() - First to resolve wins (ignores rejections)
const first = await Promise.any([
fetch('/api/a'),
fetch('/api/b')
]);
// Create resolved/rejected promises
Promise.resolve('value');
Promise.reject(new Error('failed'));
CampusKart Milestone: Cart & API
Deliverable: Working cart with localStorage + products loaded from JSON
What to Build
- Product class with id, title, price, category, seller
- Product catalog loaded from JSON file using fetch()
- Cart stored in localStorage (persists on refresh!)
- Wishlist using localStorage
- Cart total and item count display
- "Clear Cart" and individual remove
Unit III Complete!
Your CampusKart has: structure (HTML), style (CSS), interactivity (DOM/Events), and memory (localStorage/JSON).
Next unit: We give it a real backend with Node.js!
Push to GitHub — "Unit III Complete" milestone.
Video Resources
JSONPlaceholder
Practice Exercises
Exercise 1: User Cards
- Fetch users from API
- Display as cards
- Show loading state
Exercise 2: Search App
- Search input with debounce
- Fetch results from API
- Display filtered results
Exercise 3: Weather App
- Get user location
- Fetch weather data
- Display conditions
Exercise 4: CRUD App
- Create, Read, Update, Delete
- Use all HTTP methods
- Handle errors gracefully
Week 09 Summary
Key Concepts
- Objects store key-value pairs
- Prototypes enable inheritance
- JSON is text-based data format
- JSON.parse() / JSON.stringify()
- Fetch API for HTTP requests
- Promises for async operations
- async/await for cleaner code
Best Practices
- Always handle errors in async code
- Use async/await over raw Promises
- Check response.ok before parsing
- Use Promise.all for parallel requests
- Show loading states to users
Next Week
Week 10: Node.js Foundations!