javascript
examples
examples.js⚡javascript
/**
* ========================================
* 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('========================================');