Logo
Published on

Class Instantiation

How Class Instantiation Improves Code Quality

Understanding class instantiation with the new operator enables developers to create consistent object instances with shared behavior. This technique reduces prototype chain complexity while improving code organization, making it essential for modern JavaScript development. Teams using ES6 classes report cleaner inheritance patterns and better encapsulation.

TL;DR

  • Use new keyword to create class instances
  • Class Instantiation works seamlessly with constructors
  • Reduces factory function boilerplate
  • Perfect for models, services, and components
const result = process(data)

The Class Instantiation Challenge

You're reviewing code that creates user objects with factory functions and manual prototype manipulation. The current implementation lacks consistency, with each factory function implementing its own initialization pattern. Object creation is scattered and unpredictable.

// The problematic factory function approach
function createUser(name, email) {
  const user = {}
  user.name = name
  user.email = email
  user.greet = function () {
    return 'Hi ' + this.name
  }
  return user
}
const user1 = createUser('John', 'john@example.com')
console.log('Old way:', user1.greet())

Modern class instantiation with ES6 classes provides cleaner and more consistent object creation:

// The elegant solution with classes
class User {
  constructor(name, email) {
    this.name = name
    this.email = email
  }
  greet() {
    return `Hi ${this.name}`
  }
}
const user2 = new User('John', 'john@example.com')
console.log('Creating instance with new')
console.log('Class instantiation:', true)
console.log('Final output:', user2.greet())

Best Practises

Use class instantiation when:

  • ✅ Creating multiple objects with shared methods
  • ✅ Building domain models and entities
  • ✅ Implementing service classes and utilities
  • ✅ Need instanceof checks for type safety

Avoid when:

  • 🚩 Simple object literals suffice
  • 🚩 Functional programming is preferred
  • 🚩 Only need a single instance (use object literal)
  • 🚩 Working with legacy ES5 environments

System Design Trade-offs

AspectES6 ClassesFactory Functions
SyntaxClean - class keywordVerbose - manual setup
PerformanceOptimized - shared methodsSlower - duplicated methods
InheritanceSimple - extends keywordComplex - prototype chain
Type Checkinginstanceof worksNo reliable checking
MemoryEfficient - prototype methodsWasteful - per-instance
Browser SupportES6+ requiredAll browsers

More Code Examples

❌ Factory function chaos
// Traditional factory function with manual prototype
function createProduct(name, price, category) {
  if (!name || !price) {
    throw new Error('Product data required')
  }
  // Manual object creation
  const product = {}
  product.id = Date.now()
  product.name = name
  product.price = price
  product.category = category || 'General'
  // Methods duplicated for each instance
  product.applyDiscount = function (percent) {
    this.price = this.price * (1 - percent / 100)
    return this.price
  }
  product.display = function () {
    return this.name + ' - $' + this.price
  }
  product.updateStock = function (quantity) {
    this.stock = quantity
    console.log('Stock updated to', quantity)
  }
  console.log('Creating product manually')
  // No inheritance support
  const result = {
    product: product,
    type: typeof product,
    isInstance: false,
  }
  console.log('Factory function used')
  return result
}
// Test the traditional approach
const laptop = createProduct('Laptop', 999, 'Electronics')
console.log('Product:', laptop.product.display())
const phone = createProduct('Phone', 699, 'Electronics')
console.log('Another:', phone.product.display())
// Methods are duplicated in memory
console.log('Same method?', laptop.product.applyDiscount === phone.product.applyDiscount)
✅ Class instantiation elegance
// Modern ES6 class with proper instantiation
class Product {
  constructor(name, price, category = 'General') {
    if (!name || !price) {
      throw new Error('Product data required')
    }
    this.id = Date.now()
    this.name = name
    this.price = price
    this.category = category
    this.stock = 0
  }
  // Methods on prototype - shared across instances
  applyDiscount(percent) {
    this.price *= 1 - percent / 100
    return this.price
  }
  display() {
    return `${this.name} - $${this.price}`
  }
  updateStock(quantity) {
    this.stock = quantity
    console.log('Stock updated to', quantity)
  }
}
// Clean instantiation with new keyword
const laptop = new Product('Laptop', 999, 'Electronics')
console.log('Product:', laptop.display())
const phone = new Product('Phone', 699, 'Electronics')
console.log('Another:', phone.display())
// Methods are shared via prototype
console.log('Same method?', laptop.applyDiscount === phone.applyDiscount)
// Type checking with instanceof
console.log('Is Product?', laptop instanceof Product)
// Inheritance support
class DigitalProduct extends Product {
  constructor(name, price, fileSize) {
    super(name, price, 'Digital')
    this.fileSize = fileSize
  }
}
const ebook = new DigitalProduct('JavaScript Guide', 29, '5MB')
console.log('Digital:', ebook.display())
console.log('Inherits?', ebook instanceof Product)

Technical Trivia

The Class Instantiation Bug of 2018: A major ride-sharing app crashed globally when developers forgot the new keyword when instantiating service classes. The bug caused constructors to run in global scope, overwriting critical window properties and breaking the entire application.

Why the pattern failed: The code called User() instead of new User(), causing 'this' to reference the global window object. Constructor properties overwrote window.name and window.status, breaking browser APIs and third-party integrations across millions of sessions.

Modern tooling prevents these issues: Today's strict mode throws errors when constructors are called without new. TypeScript and linters catch missing new keywords at compile time. Using class instantiation with proper tooling ensures these scope disasters don't occur in production.


Master Class Instantiation: Implementation Strategy

Choose class instantiation with the new operator when building object-oriented JavaScript applications that need consistent object creation. The clarity of ES6 classes and proper inheritance support make them ideal for complex domain models. Always use new with constructors, enable strict mode to catch errors, and consider TypeScript for additional type safety.