javascript

examples

examples.js
/**
 * ========================================
 * 8.3 STATIC MEMBERS - CODE EXAMPLES
 * ========================================
 */

/**
 * EXAMPLE 1: Basic Static Method
 * Methods that don't need instance data
 */
console.log('--- Example 1: Basic Static Method ---');

class MathUtils {
  static add(a, b) {
    return a + b;
  }

  static multiply(a, b) {
    return a * b;
  }

  static clamp(value, min, max) {
    return Math.min(Math.max(value, min), max);
  }
}

console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.multiply(4, 7)); // 28
console.log(MathUtils.clamp(15, 0, 10)); // 10

// Cannot call on instances
const utils = new MathUtils();
// utils.add(1, 2);  // TypeError

/**
 * EXAMPLE 2: Static Properties
 * Shared data across all instances
 */
console.log('\n--- Example 2: Static Properties ---');

class Counter {
  static count = 0;
  static version = '1.0.0';

  constructor(name) {
    this.name = name;
    Counter.count++; // Increment static counter
  }

  static getCount() {
    return Counter.count;
  }

  static reset() {
    Counter.count = 0;
  }
}

new Counter('A');
new Counter('B');
new Counter('C');

console.log('Total counters:', Counter.count); // 3
console.log('Version:', Counter.version); // "1.0.0"

Counter.reset();
console.log('After reset:', Counter.count); // 0

/**
 * EXAMPLE 3: Static vs Instance Members
 * Understanding the difference
 */
console.log('\n--- Example 3: Static vs Instance ---');

class Demo {
  static staticProp = 'I am static';
  instanceProp = 'I am instance';

  static staticMethod() {
    return 'Called on class';
  }

  instanceMethod() {
    return 'Called on instance';
  }
}

// Static - accessed on class
console.log(Demo.staticProp); // "I am static"
console.log(Demo.staticMethod()); // "Called on class"

// Instance - accessed on objects
const demo = new Demo();
console.log(demo.instanceProp); // "I am instance"
console.log(demo.instanceMethod()); // "Called on instance"

// Cross access doesn't work
console.log(demo.staticProp); // undefined
// Demo.instanceMethod();  // TypeError

/**
 * EXAMPLE 4: Factory Methods
 * Static methods that create instances
 */
console.log('\n--- Example 4: Factory Methods ---');

class User {
  constructor(name, email, role) {
    this.name = name;
    this.email = email;
    this.role = role;
    this.createdAt = new Date();
  }

  // Factory methods
  static createAdmin(name, email) {
    return new User(name, email, 'admin');
  }

  static createModerator(name, email) {
    return new User(name, email, 'moderator');
  }

  static createGuest() {
    return new User('Guest', null, 'guest');
  }

  static fromJSON(json) {
    const data = typeof json === 'string' ? JSON.parse(json) : json;
    return new User(data.name, data.email, data.role);
  }

  describe() {
    return `${this.name} (${this.role})`;
  }
}

const admin = User.createAdmin('Alice', 'alice@example.com');
const guest = User.createGuest();
const fromData = User.fromJSON(
  '{"name":"Bob","email":"bob@example.com","role":"user"}'
);

console.log(admin.describe()); // "Alice (admin)"
console.log(guest.describe()); // "Guest (guest)"
console.log(fromData.describe()); // "Bob (user)"

/**
 * EXAMPLE 5: Singleton Pattern with Static
 * Ensuring only one instance exists
 */
console.log('\n--- Example 5: Singleton Pattern ---');

class DatabaseConnection {
  static #instance = null;
  static #config = null;

  constructor(config) {
    if (DatabaseConnection.#instance) {
      return DatabaseConnection.#instance;
    }

    this.host = config.host;
    this.port = config.port;
    this.connected = false;

    DatabaseConnection.#instance = this;
    DatabaseConnection.#config = config;
  }

  static getInstance(config = {}) {
    if (!DatabaseConnection.#instance) {
      new DatabaseConnection(config);
    }
    return DatabaseConnection.#instance;
  }

  static getConfig() {
    return { ...DatabaseConnection.#config };
  }

  connect() {
    this.connected = true;
    console.log(`Connected to ${this.host}:${this.port}`);
  }
}

const db1 = DatabaseConnection.getInstance({
  host: 'localhost',
  port: 5432,
});
const db2 = DatabaseConnection.getInstance(); // Returns same instance

console.log(db1 === db2); // true
db1.connect();
console.log(db2.connected); // true (same instance)

/**
 * EXAMPLE 6: Registry Pattern
 * Centralized component management
 */
console.log('\n--- Example 6: Registry Pattern ---');

class PluginRegistry {
  static #plugins = new Map();

  static register(name, plugin) {
    if (this.#plugins.has(name)) {
      throw new Error(`Plugin "${name}" is already registered`);
    }
    this.#plugins.set(name, plugin);
    console.log(`Registered plugin: ${name}`);
  }

  static unregister(name) {
    return this.#plugins.delete(name);
  }

  static get(name) {
    if (!this.#plugins.has(name)) {
      throw new Error(`Plugin "${name}" not found`);
    }
    return this.#plugins.get(name);
  }

  static getAll() {
    return [...this.#plugins.entries()];
  }

  static has(name) {
    return this.#plugins.has(name);
  }
}

PluginRegistry.register('logger', {
  log: (msg) => console.log(msg),
});
PluginRegistry.register('validator', {
  validate: (data) => data != null,
});

console.log('All plugins:', PluginRegistry.getAll());
console.log('Has logger:', PluginRegistry.has('logger'));

/**
 * EXAMPLE 7: Static Initialization Blocks
 * Complex static initialization (ES2022)
 */
console.log('\n--- Example 7: Static Initialization Blocks ---');

class Config {
  static defaults = {
    theme: 'light',
    language: 'en',
  };

  static settings;
  static isProduction;

  // Static initialization block
  static {
    console.log('Initializing Config class...');

    // Complex initialization logic
    this.isProduction = process.env.NODE_ENV === 'production';

    // Merge defaults with environment settings
    this.settings = {
      ...this.defaults,
      debug: !this.isProduction,
    };

    console.log('Config initialized:', this.settings);
  }

  static get(key) {
    return this.settings[key];
  }

  static set(key, value) {
    this.settings[key] = value;
  }
}

console.log('Theme:', Config.get('theme'));
console.log('Debug:', Config.get('debug'));

/**
 * EXAMPLE 8: Multiple Static Blocks
 * Sequential initialization
 */
console.log('\n--- Example 8: Multiple Static Blocks ---');

class Application {
  static version;
  static features = [];
  static ready = false;

  // First block - basic setup
  static {
    this.version = '1.0.0';
    console.log('Step 1: Version set');
  }

  // Second block - feature detection
  static {
    this.features.push('core');

    // Feature detection
    if (typeof Map !== 'undefined') {
      this.features.push('es6-collections');
    }
    if (typeof Symbol !== 'undefined') {
      this.features.push('symbols');
    }

    console.log('Step 2: Features detected:', this.features);
  }

  // Third block - finalization
  static {
    this.ready = true;
    console.log('Step 3: Application ready');
  }
}

console.log('App version:', Application.version);
console.log('App features:', Application.features);
console.log('App ready:', Application.ready);

/**
 * EXAMPLE 9: Static `this` Context
 * Understanding what `this` refers to in static context
 */
console.log('\n--- Example 9: Static this Context ---');

class Parent {
  static type = 'Parent';

  static create() {
    // 'this' refers to the class that called the method
    console.log(`Creating instance of: ${this.type}`);
    return new this();
  }

  static describe() {
    return `This is ${this.type}`;
  }
}

class Child extends Parent {
  static type = 'Child';
}

const parentInstance = Parent.create(); // "Creating instance of: Parent"
const childInstance = Child.create(); // "Creating instance of: Child"

console.log(parentInstance instanceof Parent); // true
console.log(childInstance instanceof Child); // true

/**
 * EXAMPLE 10: Static Inheritance
 * How static members are inherited
 */
console.log('\n--- Example 10: Static Inheritance ---');

class Animal {
  static kingdom = 'Animalia';

  static describe() {
    return `Kingdom: ${this.kingdom}`;
  }

  static create(name) {
    return new this(name);
  }
}

class Dog extends Animal {
  static species = 'Canis familiaris';

  constructor(name) {
    super();
    this.name = name;
  }

  static describe() {
    return `${super.describe()}, Species: ${this.species}`;
  }
}

// Static members are inherited
console.log(Dog.kingdom); // "Animalia" (inherited)
console.log(Dog.species); // "Canis familiaris" (own)
console.log(Dog.describe());

// Static factory works with inheritance
const dog = Dog.create('Rex');
console.log(dog instanceof Dog); // true

/**
 * EXAMPLE 11: Private Static Members
 * Encapsulating static data
 */
console.log('\n--- Example 11: Private Static Members ---');

class SecureStore {
  static #data = new Map();
  static #secretKey = 'my-secret-key-123';

  // Private static method
  static #encrypt(value) {
    // Simplified encryption simulation
    return Buffer.from(value).toString('base64');
  }

  static #decrypt(value) {
    return Buffer.from(value, 'base64').toString();
  }

  static set(key, value) {
    const encrypted = this.#encrypt(JSON.stringify(value));
    this.#data.set(key, encrypted);
  }

  static get(key) {
    const encrypted = this.#data.get(key);
    if (!encrypted) return undefined;
    return JSON.parse(this.#decrypt(encrypted));
  }

  static has(key) {
    return this.#data.has(key);
  }

  static delete(key) {
    return this.#data.delete(key);
  }
}

SecureStore.set('user', { name: 'Alice', role: 'admin' });
console.log('Stored user:', SecureStore.get('user'));
console.log('Has user:', SecureStore.has('user'));

// Cannot access private members
// console.log(SecureStore.#data);  // SyntaxError

/**
 * EXAMPLE 12: Static Getters and Setters
 * Computed static properties
 */
console.log('\n--- Example 12: Static Getters and Setters ---');

class Circle {
  static #defaultRadius = 1;

  constructor(radius = Circle.#defaultRadius) {
    this.radius = radius;
  }

  // Static getter
  static get PI() {
    return 3.14159265359;
  }

  static get defaultRadius() {
    return this.#defaultRadius;
  }

  // Static setter
  static set defaultRadius(value) {
    if (value <= 0) {
      throw new Error('Radius must be positive');
    }
    this.#defaultRadius = value;
  }

  // Static computed property
  static get circumferenceFormula() {
    return `C = 2 × π × r`;
  }

  area() {
    return Circle.PI * this.radius ** 2;
  }
}

console.log('PI:', Circle.PI);
console.log('Default radius:', Circle.defaultRadius);

Circle.defaultRadius = 5;
const circle = new Circle();
console.log('New default:', circle.radius); // 5
console.log('Area:', circle.area().toFixed(2));

/**
 * EXAMPLE 13: Caching with Static Members
 * Shared cache across instances
 */
console.log('\n--- Example 13: Caching ---');

class DataFetcher {
  static #cache = new Map();
  static #cacheExpiry = 5000; // 5 seconds

  static async fetch(url) {
    const now = Date.now();
    const cached = this.#cache.get(url);

    if (cached && now - cached.timestamp < this.#cacheExpiry) {
      console.log(`Cache hit for: ${url}`);
      return cached.data;
    }

    console.log(`Fetching: ${url}`);
    // Simulated fetch
    const data = { url, fetchedAt: new Date().toISOString() };

    this.#cache.set(url, {
      data,
      timestamp: now,
    });

    return data;
  }

  static clearCache() {
    this.#cache.clear();
  }

  static getCacheSize() {
    return this.#cache.size;
  }
}

// Simulate fetching
async function testCache() {
  const data1 = await DataFetcher.fetch('/api/users');
  const data2 = await DataFetcher.fetch('/api/users'); // Cache hit
  const data3 = await DataFetcher.fetch('/api/posts'); // New fetch

  console.log('Cache size:', DataFetcher.getCacheSize());
}

testCache();

/**
 * EXAMPLE 14: ID Generator
 * Generating unique IDs
 */
console.log('\n--- Example 14: ID Generator ---');

class IDGenerator {
  static #counter = 0;
  static #prefix = 'ID';

  static next() {
    return `${this.#prefix}_${++this.#counter}`;
  }

  static nextNumber() {
    return ++this.#counter;
  }

  static uuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
      const r = (Math.random() * 16) | 0;
      const v = c === 'x' ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  static setPrefix(prefix) {
    this.#prefix = prefix;
  }

  static reset() {
    this.#counter = 0;
  }
}

console.log(IDGenerator.next()); // ID_1
console.log(IDGenerator.next()); // ID_2

IDGenerator.setPrefix('USER');
console.log(IDGenerator.next()); // USER_3

console.log('UUID:', IDGenerator.uuid());

/**
 * EXAMPLE 15: Configuration Manager
 * Environment-based configuration
 */
console.log('\n--- Example 15: Configuration Manager ---');

class ConfigManager {
  static #configs = new Map();
  static #env = 'development';

  // Initialize default configs
  static {
    this.#configs.set('development', {
      apiUrl: 'http://localhost:3000',
      debug: true,
      logLevel: 'verbose',
    });

    this.#configs.set('production', {
      apiUrl: 'https://api.example.com',
      debug: false,
      logLevel: 'error',
    });

    this.#configs.set('test', {
      apiUrl: 'http://localhost:3001',
      debug: true,
      logLevel: 'debug',
    });
  }

  static setEnvironment(env) {
    if (!this.#configs.has(env)) {
      throw new Error(`Unknown environment: ${env}`);
    }
    this.#env = env;
  }

  static get(key) {
    const config = this.#configs.get(this.#env);
    return config[key];
  }

  static getAll() {
    return { ...this.#configs.get(this.#env) };
  }

  static get environment() {
    return this.#env;
  }
}

console.log('Environment:', ConfigManager.environment);
console.log('API URL:', ConfigManager.get('apiUrl'));
console.log('All config:', ConfigManager.getAll());

ConfigManager.setEnvironment('production');
console.log('Production API:', ConfigManager.get('apiUrl'));

/**
 * EXAMPLE 16: Event Bus (Static Pattern)
 * Application-wide event system
 */
console.log('\n--- Example 16: Static Event Bus ---');

class EventBus {
  static #listeners = new Map();

  static on(event, callback) {
    if (!this.#listeners.has(event)) {
      this.#listeners.set(event, new Set());
    }
    this.#listeners.get(event).add(callback);

    // Return unsubscribe function
    return () => this.off(event, callback);
  }

  static off(event, callback) {
    if (this.#listeners.has(event)) {
      this.#listeners.get(event).delete(callback);
    }
  }

  static emit(event, ...args) {
    if (this.#listeners.has(event)) {
      for (const callback of this.#listeners.get(event)) {
        callback(...args);
      }
    }
  }

  static once(event, callback) {
    const wrapper = (...args) => {
      callback(...args);
      this.off(event, wrapper);
    };
    return this.on(event, wrapper);
  }

  static clear(event) {
    if (event) {
      this.#listeners.delete(event);
    } else {
      this.#listeners.clear();
    }
  }
}

// Usage
const unsubscribe = EventBus.on('user:login', (user) => {
  console.log(`User logged in: ${user.name}`);
});

EventBus.once('app:ready', () => {
  console.log('App is ready!');
});

EventBus.emit('user:login', { name: 'Alice' });
EventBus.emit('app:ready');
EventBus.emit('app:ready'); // Won't fire again (once)

unsubscribe(); // Remove listener
EventBus.emit('user:login', { name: 'Bob' }); // Won't fire

/**
 * EXAMPLE 17: Object Pool Pattern
 * Reusing expensive objects
 */
console.log('\n--- Example 17: Object Pool ---');

class Connection {
  constructor(id) {
    this.id = id;
    this.inUse = false;
    console.log(`Connection ${id} created`);
  }

  query(sql) {
    console.log(`Connection ${this.id} executing: ${sql}`);
    return { result: 'data' };
  }
}

class ConnectionPool {
  static #pool = [];
  static #maxSize = 5;
  static #connectionId = 0;

  static acquire() {
    // Find available connection
    let connection = this.#pool.find((c) => !c.inUse);

    if (!connection) {
      // Create new if pool not full
      if (this.#pool.length < this.#maxSize) {
        connection = new Connection(++this.#connectionId);
        this.#pool.push(connection);
      } else {
        throw new Error('Connection pool exhausted');
      }
    }

    connection.inUse = true;
    return connection;
  }

  static release(connection) {
    connection.inUse = false;
    console.log(`Connection ${connection.id} released`);
  }

  static get available() {
    return this.#pool.filter((c) => !c.inUse).length;
  }

  static get total() {
    return this.#pool.length;
  }
}

const conn1 = ConnectionPool.acquire();
const conn2 = ConnectionPool.acquire();

console.log(`Available: ${ConnectionPool.available}/${ConnectionPool.total}`);

conn1.query('SELECT * FROM users');
ConnectionPool.release(conn1);

console.log(`Available: ${ConnectionPool.available}/${ConnectionPool.total}`);

/**
 * EXAMPLE 18: Static Validation Utilities
 * Common validation functions
 */
console.log('\n--- Example 18: Validation Utilities ---');

class Validator {
  static isEmail(value) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
  }

  static isURL(value) {
    try {
      new URL(value);
      return true;
    } catch {
      return false;
    }
  }

  static isPhone(value) {
    return /^\+?[\d\s-]{10,}$/.test(value);
  }

  static isStrongPassword(value) {
    const minLength = value.length >= 8;
    const hasUpper = /[A-Z]/.test(value);
    const hasLower = /[a-z]/.test(value);
    const hasNumber = /[0-9]/.test(value);
    const hasSpecial = /[!@#$%^&*]/.test(value);

    return {
      valid: minLength && hasUpper && hasLower && hasNumber && hasSpecial,
      checks: { minLength, hasUpper, hasLower, hasNumber, hasSpecial },
    };
  }

  static validate(value, ...rules) {
    const errors = [];
    for (const rule of rules) {
      const result = rule(value);
      if (result !== true) {
        errors.push(result);
      }
    }
    return { valid: errors.length === 0, errors };
  }
}

console.log('Email valid:', Validator.isEmail('test@example.com'));
console.log('URL valid:', Validator.isURL('https://example.com'));
console.log('Password check:', Validator.isStrongPassword('Abc123!@#'));

// Custom validation
const result = Validator.validate(
  'hello',
  (v) => v.length >= 3 || 'Too short',
  (v) => v.length <= 10 || 'Too long',
  (v) => /^[a-z]+$/.test(v) || 'Only lowercase letters'
);
console.log('Custom validation:', result);

/**
 * EXAMPLE 19: Static Comparators
 * Reusable comparison functions
 */
console.log('\n--- Example 19: Static Comparators ---');

class Comparators {
  static byProperty(property, descending = false) {
    return (a, b) => {
      const valA = a[property];
      const valB = b[property];
      const result = valA < valB ? -1 : valA > valB ? 1 : 0;
      return descending ? -result : result;
    };
  }

  static byString(property, descending = false) {
    return (a, b) => {
      const result = String(a[property]).localeCompare(String(b[property]));
      return descending ? -result : result;
    };
  }

  static byDate(property, descending = false) {
    return (a, b) => {
      const result = new Date(a[property]) - new Date(b[property]);
      return descending ? -result : result;
    };
  }

  static compose(...comparators) {
    return (a, b) => {
      for (const comparator of comparators) {
        const result = comparator(a, b);
        if (result !== 0) return result;
      }
      return 0;
    };
  }
}

const users = [
  { name: 'Charlie', age: 30, joinDate: '2023-01-15' },
  { name: 'Alice', age: 25, joinDate: '2023-03-20' },
  { name: 'Bob', age: 25, joinDate: '2023-02-10' },
];

// Sort by age, then by name
const sorted = [...users].sort(
  Comparators.compose(
    Comparators.byProperty('age'),
    Comparators.byString('name')
  )
);

console.log(
  'Sorted:',
  sorted.map((u) => `${u.name}(${u.age})`)
);

/**
 * EXAMPLE 20: Complete Static Service Example
 * Combining multiple static patterns
 */
console.log('\n--- Example 20: Complete Service Example ---');

class ApiService {
  static #baseUrl = 'https://api.example.com';
  static #token = null;
  static #requestCount = 0;
  static #cache = new Map();

  // Initialize with static block
  static {
    console.log('ApiService initialized');
    this.#loadToken();
  }

  static #loadToken() {
    // Simulated token loading
    this.#token = 'cached-token-123';
  }

  static setBaseUrl(url) {
    this.#baseUrl = url;
  }

  static setToken(token) {
    this.#token = token;
  }

  static async #makeRequest(method, endpoint, data = null) {
    this.#requestCount++;

    const url = `${this.#baseUrl}${endpoint}`;
    console.log(`[${method}] ${url}`);

    // Simulated response
    return {
      status: 200,
      data: { success: true, ...data },
    };
  }

  static async get(endpoint, useCache = true) {
    if (useCache && this.#cache.has(endpoint)) {
      console.log(`Cache hit: ${endpoint}`);
      return this.#cache.get(endpoint);
    }

    const result = await this.#makeRequest('GET', endpoint);

    if (useCache) {
      this.#cache.set(endpoint, result);
    }

    return result;
  }

  static async post(endpoint, data) {
    return this.#makeRequest('POST', endpoint, data);
  }

  static async put(endpoint, data) {
    return this.#makeRequest('PUT', endpoint, data);
  }

  static async delete(endpoint) {
    return this.#makeRequest('DELETE', endpoint);
  }

  static clearCache() {
    this.#cache.clear();
  }

  static get stats() {
    return {
      requestCount: this.#requestCount,
      cacheSize: this.#cache.size,
      hasToken: !!this.#token,
    };
  }
}

// Usage
async function demoApiService() {
  const users = await ApiService.get('/users');
  console.log('Users:', users);

  const cachedUsers = await ApiService.get('/users'); // Cache hit
  console.log('Cached:', cachedUsers);

  const newUser = await ApiService.post('/users', { name: 'Alice' });
  console.log('Created:', newUser);

  console.log('Stats:', ApiService.stats);
}

demoApiService();

console.log('\n========================================');
console.log('End of Static Members Examples');
console.log('========================================');
Examples - JavaScript Tutorial | DeepML