What are JavaScript Objects?
In JavaScript, objects are the fundamental building blocks of the language. They're collections of related data and functionality, stored as key-value pairs called properties and methods.
Think of an object like a backpack - it can hold various items (properties), and it can have different functions (methods) like opening, closing, or adjusting straps. Just as a backpack organizes your personal items, objects organize related data and behavior.
Basic Object Structure
// Property: A key-value pair
// Method: A function stored as a property value
const backpack = {
// Properties
color: "blue",
volume: 30,
pockets: 5,
// Methods
open: function() {
console.log("Backpack is now open");
},
close: function() {
console.log("Backpack is now closed");
}
};
Ways to Create Objects
JavaScript provides several ways to create objects, each with its own use cases and advantages.
Object Literals
The simplest and most common way to create objects is using object literals, which use curly braces.
const car = {
make: "Toyota",
model: "Corolla",
year: 2023,
isElectric: false,
start: function() {
console.log("Engine started!");
}
};
Object literals are ideal for one-off objects or configuration objects that won't need multiple instances.
The Object Constructor
You can use the built-in Object constructor function with the new keyword.
const person = new Object();
person.name = "Maria";
person.age = 28;
person.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
This approach is less common but can be useful when you need to create an object dynamically.
Object.create() Method
The Object.create() method creates a new object with the specified prototype object.
const vehiclePrototype = {
start: function() {
console.log("Engine started!");
},
stop: function() {
console.log("Engine stopped!");
}
};
const myCar = Object.create(vehiclePrototype);
myCar.make = "Honda";
myCar.model = "Civic";
myCar.start(); // "Engine started!"
This method is powerful for implementing prototypal inheritance.
Factory Functions
Factory functions are regular functions that return new objects. They're a pattern for creating multiple similar objects without using the new keyword.
function createUser(name, email, role) {
return {
name,
email,
role,
createdAt: new Date(),
isActive: true,
login() {
console.log(`${this.name} has logged in`);
},
logout() {
console.log(`${this.name} has logged out`);
}
};
}
const user1 = createUser("Alice", "alice@example.com", "admin");
const user2 = createUser("Bob", "bob@example.com", "editor");
user1.login(); // "Alice has logged in"
Factory functions are great for creating multiple objects with privacy through closures. Notice we're using the ES6 shorthand property names where the variable name becomes the property name.
Constructor Functions
Constructor functions are used with the new keyword and follow the convention of starting with a capital letter.
function Product(name, price, category) {
this.name = name;
this.price = price;
this.category = category;
this.isInStock = true;
this.displayInfo = function() {
console.log(`${this.name} - $${this.price} (${this.category})`);
};
}
const laptop = new Product("MacBook Pro", 1299, "Electronics");
const chair = new Product("Ergonomic Chair", 249, "Furniture");
laptop.displayInfo(); // "MacBook Pro - $1299 (Electronics)"
When you use the new keyword with a constructor function, several things happen:
- A new empty object is created
- The function is called with
thisset to the new object - The new object is linked to the constructor's prototype
- The function implicitly returns the object (unless it explicitly returns something else)
ES6 Classes
ES6 introduced class syntax, which is syntactic sugar over JavaScript's existing prototype-based inheritance.
class Animal {
constructor(name, species) {
this.name = name;
this.species = species;
this.createdAt = new Date();
}
makeSound() {
console.log("Some generic animal sound");
}
describe() {
console.log(`${this.name} is a ${this.species}`);
}
}
const dog = new Animal("Rex", "dog");
dog.describe(); // "Rex is a dog"
Classes provide a cleaner, more familiar syntax for creating objects and implementing inheritance, especially for developers coming from class-based languages.
Real-World Object Usage Examples
E-commerce Product System
class Product {
constructor(id, name, price) {
this.id = id;
this.name = name;
this.price = price;
this.inventory = 0;
}
applyDiscount(percentage) {
return this.price * (1 - percentage/100);
}
updateInventory(amount) {
this.inventory += amount;
return this.inventory;
}
}
class DigitalProduct extends Product {
constructor(id, name, price, fileSize) {
super(id, name, price);
this.fileSize = fileSize;
this.inventory = Infinity; // Digital products have unlimited inventory
}
generateDownloadLink() {
return `https://example.com/downloads/${this.id}`;
}
}
// Usage
const physicalBook = new Product(101, "JavaScript: The Good Parts", 29.99);
physicalBook.updateInventory(50);
const ebook = new DigitalProduct(102, "JavaScript: The Good Parts (Digital)", 19.99, "4.2MB");
console.log(ebook.generateDownloadLink()); // "https://example.com/downloads/102"
console.log(`Sale price: $${ebook.applyDiscount(15).toFixed(2)}`); // "Sale price: $16.99"
User Authentication System
class User {
constructor(username, email) {
this.username = username;
this.email = email;
this.lastLogin = null;
this._isLoggedIn = false;
this._passwordHash = null;
}
login(password) {
// In real apps, you'd verify the password hash
if (this._passwordHash && this._verifyPassword(password)) {
this._isLoggedIn = true;
this.lastLogin = new Date();
console.log(`${this.username} logged in successfully`);
return true;
}
console.log("Login failed");
return false;
}
logout() {
if (this._isLoggedIn) {
this._isLoggedIn = false;
console.log(`${this.username} logged out`);
}
}
setPassword(password) {
// In real apps, you'd hash the password
this._passwordHash = `hashed_${password}`;
}
_verifyPassword(password) {
// Simplified password verification
return this._passwordHash === `hashed_${password}`;
}
get loginStatus() {
return this._isLoggedIn ? "Online" : "Offline";
}
}
// Usage
const alice = new User("alice", "alice@example.com");
alice.setPassword("securePassword123");
alice.login("securePassword123"); // "alice logged in successfully"
console.log(alice.loginStatus); // "Online"
alice.logout(); // "alice logged out"
Dynamic Property Access
JavaScript allows dynamic access and modification of object properties:
const settings = {
theme: "dark",
fontSize: 16,
notifications: true
};
// Accessing with dot notation
console.log(settings.theme); // "dark"
// Accessing with bracket notation
const property = "fontSize";
console.log(settings[property]); // 16
// Adding properties dynamically
settings.language = "English";
settings["timeZone"] = "UTC-5";
// Deleting properties
delete settings.notifications;
Bracket notation is especially powerful for dynamic property access based on variables or expressions.
Object Property Descriptors
JavaScript objects have property descriptors that control how properties behave:
const user = {};
Object.defineProperty(user, 'name', {
value: 'John',
writable: true, // Can the value be changed?
enumerable: true, // Will it show up in for...in loops?
configurable: true // Can this property be deleted or its attributes modified?
});
Object.defineProperty(user, 'id', {
value: 12345,
writable: false, // Read-only property
enumerable: false, // Won't show up in Object.keys() or for...in
configurable: false // Can't be deleted or reconfigured
});
// Trying to modify the read-only property
user.id = 54321; // This won't work (in strict mode, throws an error)
console.log(user.id); // Still 12345
Property descriptors allow fine-grained control over how properties behave.
Practice Activities
Activity 1: Create a Book Manager
Create an object-oriented system to manage a collection of books. Implement classes or constructor functions for books and a library to manage them.
Activity 2: Extend Built-in Objects
Extend JavaScript's built-in Array object with helpful methods like first(), last(), and random() using the prototype.
Activity 3: Bank Account System
Implement a bank account system with different account types (checking, savings) that share common behaviors but have unique properties.
Summary
In this lecture, we've explored:
- The concept of objects as collections of related data and functionality
- Different ways to create objects: literals, constructors, Object.create(), factory functions, etc.
- ES6 class syntax for creating object templates
- Property access, dynamic properties, and property descriptors
- Real-world examples of how objects are used in applications
Objects are fundamental to JavaScript programming, and understanding how to create and manipulate them is essential for building modern web applications.