javascript
examples
examples.jsā”javascript
// ============================================================================
// 14.1 Module Systems Overview - Examples
// ============================================================================
// This file demonstrates the evolution of JavaScript module systems
// from early patterns to modern ES Modules.
// ============================================================================
// 1. THE PROBLEM: Global Namespace Pollution (Before Modules)
// ============================================================================
// In early JavaScript, all code shared the global namespace
// This led to naming conflicts and maintenance nightmares
// file1.js
var userName = 'Alice';
function greet() {
console.log('Hello from file1!');
}
// file2.js (loaded after file1.js)
var userName = 'Bob'; // Overwrites file1's userName!
function greet() {
// Overwrites file1's greet!
console.log('Hello from file2!');
}
// Result: Only file2's values exist - file1's are lost!
console.log('Example 1 - Global pollution:', userName); // "Bob"
// ============================================================================
// 2. SOLUTION 1: Namespace Pattern (2000s)
// ============================================================================
// Wrap everything in a single global object
var MyApp = MyApp || {};
MyApp.utils = {
formatDate: function (date) {
return date.toISOString().split('T')[0];
},
capitalize: function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
},
};
MyApp.models = {
User: function (name) {
this.name = name;
},
};
// Usage
console.log('Example 2 - Namespace pattern:');
console.log(MyApp.utils.formatDate(new Date()));
console.log(MyApp.utils.capitalize('hello'));
// ============================================================================
// 3. SOLUTION 2: IIFE Module Pattern (2005+)
// ============================================================================
// Immediately Invoked Function Expression creates private scope
var CounterModule = (function () {
// Private variables - not accessible outside
var count = 0;
var history = [];
// Private function
function log(action) {
history.push({ action: action, count: count, time: new Date() });
}
// Public API (revealed)
return {
increment: function () {
count++;
log('increment');
return count;
},
decrement: function () {
count--;
log('decrement');
return count;
},
getCount: function () {
return count;
},
getHistory: function () {
return [...history]; // Return copy to protect internal state
},
};
})();
console.log('\nExample 3 - IIFE Module Pattern:');
console.log('Initial count:', CounterModule.getCount()); // 0
CounterModule.increment();
CounterModule.increment();
CounterModule.decrement();
console.log('After operations:', CounterModule.getCount()); // 1
console.log('History:', CounterModule.getHistory());
// console.log(count); // ReferenceError - count is private!
// ============================================================================
// 4. SOLUTION 3: Revealing Module Pattern
// ============================================================================
var Calculator = (function () {
// All functions defined as private first
var result = 0;
function add(x) {
result += x;
return this;
}
function subtract(x) {
result -= x;
return this;
}
function multiply(x) {
result *= x;
return this;
}
function divide(x) {
if (x === 0) throw new Error('Division by zero');
result /= x;
return this;
}
function getResult() {
return result;
}
function reset() {
result = 0;
return this;
}
// Reveal public pointers to private functions
return {
add: add,
subtract: subtract,
multiply: multiply,
divide: divide,
getResult: getResult,
reset: reset,
};
})();
console.log('\nExample 4 - Revealing Module Pattern:');
Calculator.reset().add(10).multiply(2).subtract(5);
console.log('Calculator result:', Calculator.getResult()); // 15
// ============================================================================
// 5. SOLUTION 4: Module with Dependencies
// ============================================================================
// Passing dependencies as parameters (early dependency injection)
var UserService = (function (storage, validator) {
var users = storage.load('users') || [];
return {
addUser: function (user) {
if (validator.isValidUser(user)) {
users.push(user);
storage.save('users', users);
return true;
}
return false;
},
getUsers: function () {
return [...users];
},
};
})(
// Mock storage dependency
{
data: {},
load: function (key) {
return this.data[key];
},
save: function (key, value) {
this.data[key] = value;
},
},
// Mock validator dependency
{
isValidUser: function (user) {
return user && user.name && user.email;
},
}
);
console.log('\nExample 5 - Module with Dependencies:');
UserService.addUser({ name: 'Alice', email: 'alice@example.com' });
UserService.addUser({ name: 'Bob', email: 'bob@example.com' });
console.log('Users:', UserService.getUsers());
// ============================================================================
// 6. COMMONJS PATTERN (Node.js style - simulated)
// ============================================================================
// In Node.js, each file is a module with its own scope
// This is a simulation of how CommonJS works
// Simulated module system
var CommonJSSimulator = (function () {
var modules = {};
var cache = {};
function define(name, factory) {
modules[name] = factory;
}
function require(name) {
if (cache[name]) {
return cache[name].exports;
}
var module = { exports: {} };
cache[name] = module;
modules[name](module, module.exports, require);
return module.exports;
}
return { define: define, require: require };
})();
// Define a module
CommonJSSimulator.define('math', function (module, exports, require) {
exports.add = function (a, b) {
return a + b;
};
exports.multiply = function (a, b) {
return a * b;
};
exports.PI = 3.14159;
});
// Define another module that depends on math
CommonJSSimulator.define('circle', function (module, exports, require) {
var math = require('math');
exports.area = function (radius) {
return math.PI * math.multiply(radius, radius);
};
exports.circumference = function (radius) {
return 2 * math.PI * radius;
};
});
// Use the modules
console.log('\nExample 6 - CommonJS Simulation:');
var circle = CommonJSSimulator.require('circle');
console.log('Circle area (r=5):', circle.area(5).toFixed(2));
console.log('Circle circumference (r=5):', circle.circumference(5).toFixed(2));
// ============================================================================
// 7. AMD PATTERN (RequireJS style - simulated)
// ============================================================================
// Asynchronous Module Definition - designed for browsers
var AMDSimulator = (function () {
var modules = {};
var definitions = {};
function define(name, dependencies, factory) {
definitions[name] = { deps: dependencies, factory: factory };
}
function require(dependencies, callback) {
var resolvedDeps = dependencies.map(function (dep) {
return getModule(dep);
});
callback.apply(null, resolvedDeps);
}
function getModule(name) {
if (modules[name]) return modules[name];
var def = definitions[name];
if (!def) throw new Error('Module not found: ' + name);
var deps = def.deps.map(getModule);
modules[name] = def.factory.apply(null, deps);
return modules[name];
}
return { define: define, require: require };
})();
// Define modules AMD style
AMDSimulator.define('utils', [], function () {
return {
formatCurrency: function (amount) {
return '$' + amount.toFixed(2);
},
};
});
AMDSimulator.define('product', ['utils'], function (utils) {
function Product(name, price) {
this.name = name;
this.price = price;
}
Product.prototype.getFormattedPrice = function () {
return utils.formatCurrency(this.price);
};
return Product;
});
// Use AMD modules
console.log('\nExample 7 - AMD Simulation:');
AMDSimulator.require(['product'], function (Product) {
var laptop = new Product('Laptop', 999.99);
console.log(laptop.name + ': ' + laptop.getFormattedPrice());
});
// ============================================================================
// 8. UMD PATTERN (Universal Module Definition)
// ============================================================================
// UMD works in both CommonJS and AMD environments
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['dependency'], factory);
} else if (typeof module === 'object' && module.exports) {
// CommonJS
module.exports = factory(require('dependency'));
} else {
// Browser globals
root.MyLibrary = factory(root.Dependency);
}
})(typeof self !== 'undefined' ? self : this, function (dependency) {
// Library code here
return {
version: '1.0.0',
greet: function (name) {
return 'Hello, ' + name + '!';
},
};
});
console.log('\nExample 8 - UMD Pattern:');
console.log(
'UMD pattern creates modules that work everywhere (AMD, CommonJS, Browser)'
);
// ============================================================================
// 9. ES MODULES PREVIEW (Modern Standard)
// ============================================================================
// ES Modules (ESM) are the official standard
// Note: This is just a demonstration of syntax - actual ESM requires
// file extensions and proper module context
console.log('\nExample 9 - ES Modules Syntax Preview:');
console.log(`
// math.js (ES Module)
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export default class Calculator { ... }
// main.js
import Calculator, { PI, add } from './math.js';
import * as MathUtils from './math.js';
// Dynamic import
const module = await import('./math.js');
`);
// ============================================================================
// 10. MODULE SYSTEMS COMPARISON
// ============================================================================
console.log('\nExample 10 - Module Systems Comparison:');
console.log(`
āāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāā
ā System ā Environment ā Loading ā Syntax ā
āāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāā¤
ā IIFE ā Browser ā Script tags ā (function(){})() ā
ā CommonJS ā Node.js ā Synchronous ā require/exports ā
ā AMD ā Browser ā Async ā define/require ā
ā UMD ā Both ā Both ā Wrapper pattern ā
ā ES Modules ā Both ā Async ā import/export ā
āāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāā
`);
// ============================================================================
// SUMMARY
// ============================================================================
console.log('\n=== Module Systems Evolution Summary ===');
console.log('1. Global scripts ā Namespace pollution problems');
console.log('2. IIFE pattern ā Encapsulation via closures');
console.log('3. CommonJS ā Synchronous loading for Node.js');
console.log('4. AMD ā Asynchronous loading for browsers');
console.log('5. UMD ā Universal compatibility wrapper');
console.log('6. ES Modules ā Official standard, best of both worlds');