1.0 What are modules
Modules play a crucial role in organizing and structuring code within an application. They allow developers to break down large codebases into smaller, manageable pieces. In this article, we’ll delve into the concept of modules, their evolution, and how JavaScript and TypeScript handle them.
It is a technique which keep the code organizes in any programme. Java Script default way of creating object using literals is one of the ways of module pattern.
1.1 Object literals
1var myModule = {
2 // data
3}
- The above is also a pattern where data can be organized within the curly brackets. This method has some shortcoming from data hiding point of view which is deemed essential in
object based or object oriented programming.
1.2 Module Pattern
- It is a
unique style of writing codethat makes the code behave as a separate unit known as amodule. It is commonly achieved by making use of Immediately Invoked function expression that creates an anonymous function. The code inside the anonymous function lives in a scope that provides privacy and state.
1 (function() {
2 // declare private variables functions
3 return {
4 // declare public variables or functions
5 }
6})();
- In above section variables declared as private are only accessible inside this function and are not visible outside thus providing
data encapsulationlet’s look at this example below.
1 var myModule = (function(){
2 var guestCounter = 0;
3 return {
4 increaseCounter = function () { return guestCounter++;},
5 restartCounter = function () { guestCounter = 0;}
6 };
7 });
8 // Testing the module
9 // Using the module upon the guest entry
10 myModule.increseCounter();
11 // When need to restart the counter
12 myModule.restartCounter();
- The difference between using object literal as opposed to module pattern is that here the local variable
guestCounteris hidden from the global scope and tightly encapsulated. The two functions used within this module can not be accessed by the outside world except the variable receiving the return object thus regarded as effectively name-spaced. What it means that the functions defined inside the module can only be accessed by aname-space ( variable receiving the return object)hence a template of a module can be defined in a following way
1var nameSpace = function () {
2 // private variable
3 var privateVariable1 = 0
4 var privateVariable2 = 1
5 // private method
6 var privateMethod = function (anyValue) {
7 console.log(anyValue)
8 }
9 // object that needs to be returned so available to nameSpace
10 return {
11 publicVariable: 'public',
12 publicFunction: function (value) {
13 privateVariable1++
14 privateVariable2--
15 privateMethod(value)
16 }
17 } // end of return
18}
- From the above pattern it can be seen that avoiding object literal and using module pattern, significant amount of benefits can be achieved which leads to safe programming. The methods which needs to be exposed can either be defined within the return object or can be defined separately as functions and can be referred in the return object as shown below.
1 var nameSpace = (function (){
2 //private variable
3 //private method
4 //method to Expose can be defined here
5 var printName = function (){ console.log("Printing Name")}
6 //Object to return
7 return {
8 print:printName, // function defined above
9 ......
10 }
11 });
1.3 Prototype Design Pattern
- Below a JavaScript constructor function is created then a method name
runis added to this object. This is a how it is done. The propertyprototypeis inherited implicitly when a JavaScript object is created
1 var OrganiteModel = function () {
2 this.shape: "pyramid",
3 this.energyType:"Scalar",
4 this.use:"nonCommercial"
5 };
6 OrganiteModel.prototype.run = function (){
7 // running
8 };
- In above construction an instance can be created using a constructor function which will retain the state initialized in the constructor sharing the function
runwith other instances. Adding function to prototype can done in the following manner
Note the outside world can not touch anything except what is exposed to them by returning an object with two properties.
1var OrganiteModel = function () {
2 this.shape = 'pyramid'
3 this.energyType = 'Scalar'
4 this.use = 'nonCommercial'
5}
6
7// Adding prototype
8OrganiteModel.prototype = (function () {
9 var on = function () {
10 console.log('It has been turned on')
11 }
12 var off = function () {
13 console.log('It is off!')
14 }
15 //return
16 return {
17 // returning two properties
18 turnOrganiteOn: on,
19 turnOrganiteOff: off
20 }
21})()
22var myOrganite = new OrganiteModel()
23myOrganite.turnOrganiteOn()
24myOrganite.turnOrganiteOff()
- The above example also shows how function
onandoffare protected from outside world.
1.4 Observer Design Pattern
- In above example no
- is passed to this module but if passed, the data within this module can be used as their local variables. For example the following code accepts two parameters to be used in this module.
1 var myApp = {};
2 ..........
3 ..........
4 // other code
5
6 // module
7 (function (app,$) {
8 // app and $ are available inside the module
9 .........//some code
10 }(myApp,JQuery));
In the above code JQuery is a third party global but myApp is probably the only one global defined at the top level. When a third party global is used in your module you are said to have
importeda module. And the third party library, module or a package used in your program is said to have exported their package. In case of JQuery you would either include it in your webpage or you would use in other method to load it in your programme. JQuery defines one global variable$that is used to get the functionality provided by this library.The global variable above
myAppcan be declared inside the module too so it can be used with the rest of the code and return to be used by other code in the programme. Returning the object using this pattern is known asexporting module. The receiving variable is said to become the closure that have access to internal state of the object returned. Let’s look this scenario below.
1 var myCar = ( function () {
2 var myApp = {};
3 var itsName = "Farari";
4 var value = 300,000; // private variable
5 var getValue : function(){return value;}
6 //module properties
7 myApp.name = itsName;
8 myApp.getName = function() {console.log("myApp name is" + myApp.name);}
9 //
10 return myApp;
11 }());
2.0 Factory pattern
Module systems in js
- CommonJs
- AMD
- UMD
- ES
2.1 NodeJS module Systems
- NodeJs uses CommonJs
- Code resides in separate files
- Code in one file is not visible to another file unless it is exported explicitly.
- From a simple variable to object can be exported.
- Usually a function is exported and used in other files.
- Follow the standards require if there is any doubt.
- The file name becomes the module name which is loaded using require with the correct path.
- It has two key words
exportsandrequire. NodeJs has amodule.exportsproperty that can assigned a new value. - Example showing a function is exported
1var addThem = function (x, y) {
2 return x + y
3}
4module.exports = addThem
Save this code in file addThem.js and have it available anywhere in node by first using the require method using the correct path.
1var addThem = require('addThem')
2or
3var adding = require('./addThem')
4or
5var result = require('addThem')
6
7result(10, 20) // 30 or
8
9// do it directly at the time of lading.
10require('addThem')(10, 20) //30
- There are some disadvantages of CommonJs
- You can have only one module in a JavaScript file.
- If you want to use it in a browser, additional tools are required.
- Not suitable in some situation being synchronous.
2.2 ES modules
- They keyword
exportis used before any line of code to be exported, it may be avariable, functionetc. Give this file any name, it becomes a module and import it in another file. - When importing use
import { my-file-name} form./my-file-name.js`
2.3 Different way of using export and import module
- Named export and Named import
- Whatever you are exporting from your module should have a name.
- variable name, class name or a function name. It can be used if you only use a particular property and not the whole file.
1// js/sum.js
2export function sum(a, b) {
3 return a + b
4}
5// there are more exports present
6export function square(a, b) {
7 return a * b
8}
- And when you want to import only one function in another file
1// main.js
2import {sum} from './sum.js`
3//use sum here
2.Default export and default import
- You add the
defaultkey word before what you like to export. - Do no use more than one default export, though you are allowed to have more than one.
- In this case curly brackets are removed otherwise you will get an error.
- Default export as a named export
- JavaScript allows an alias using the
askeyword, but when you export it you use an export clause, you must useasto work otherwise it will throw an error. The clause is given below.
- JavaScript allows an alias using the
1// file sum.js
2function sum ( a, b) {
3 return (a + b);
4
5// named default export
6export {
7 sum as default
8 // other items can be present here.
9}
10
11// Note in export you can have number of items and can rename them as well.
- Rename exports and Name imports
- JavaScript allows you to rename your export and use the new name to be exported
1// sum.js
2
3function sum(a, b) {
4 return a + b
5}
6export { sum as add }
- When importing use
1// main file
2import { add } from './sum.js`
3
4console.log ( add(2 + 3));
- Namespace import
- So far a we used a named property to be exported and imported, but you can use all of them using namespace
*. This symbol*means everything.
- So far a we used a named property to be exported and imported, but you can use all of them using namespace
import * as <newName> from ./<file-name.js>
newName.sum(2,8)
2.4 Dynamic imports
- The above are called static imports, they must be at the top level of the file and you can not use inside a block.
- In dynamic imports an
import()operator can be used to load the code on demand. For more see the articles below.
Typescript and modules
1. Modules in JavaScript Before ES6
Before ECMAScript 6 (ES6), JavaScript lacked a standardized module system. However, developers adopted two popular strategies:
CommonJS (CJS): CommonJS was widely used in server-side environments (e.g., Node.js). It allowed developers to define modules using
requireandmodule.exports. CommonJS modules were synchronous and loaded dynamically at runtime.Asynchronous Module Definition (AMD): AMD emerged for browser-based applications. It used libraries like RequireJS to load modules asynchronously. AMD modules were suitable for client-side development and supported dynamic loading.
2. Modules in JavaScript with ES6
ES6 introduced native support for modules in JavaScript. The ES6 module system provides a unified syntax for defining and importing/exporting modules. Key features include:
importandexportKeywords: Developers can useimportto bring in functionality from other modules andexportto expose functionality from their own modules.Static Analysis: ES6 modules are statically analyzable, allowing tools to optimize and tree-shake unused code during bundling.
3. TypeScript’s Role in Modules
TypeScript shares the same module concept as JavaScript. Here’s how TypeScript handles modules:
Unified Syntax: TypeScript’s module system aligns with the ES6 module syntax. Developers can use
importandexportjust like in ES6.Targeting Different Module Loaders: TypeScript allows developers to target various module loaders when emitting JavaScript code. Supported targets include Node.js (CommonJS), require.js (AMD), Universal Module Definition (UMD), SystemJS, and native ES6 modules.
Conclusion
Modules are essential for maintaining code quality, reusability, and scalability. Whether you’re working with JavaScript or TypeScript, understanding modules and their role is crucial for building robust applications.
Remember to explore further resources and experiment with modules in your projects. Happy coding! 🚀
References:
- How To Use Modules in TypeScript | DigitalOcean ¹
- TypeScript Modules ²
- TypeScript: Documentation - Modules - Theory ³
- Understanding JavaScript Modules As A TypeScript User - geekAbyte ⁴
Source: Conversation with Bing, 14/05/2024 (1) How To Use Modules in TypeScript | DigitalOcean. https://www.digitalocean.com/community/tutorials/how-to-use-modules-in-typescript. (2) TypeScript Modules. https://www.typescripttutorial.net/typescript-tutorial/typescript-modules/. (3) TypeScript: Documentation - Modules - Theory. https://www.typescriptlang.org/docs/handbook/modules/theory.html. (4) Understanding JavaScript Modules As A TypeScript User - geekAbyte. https://www.geekabyte.io/2018/12/understanding-javascript-modules-as.html.















