In addition there is also making modules where a module is used as a way to play with a state that is held in the module itself as a local variable to the module which I would not recommend doing. With that said there is also having modules where a public method is used to create a new independent state object that I use outside of the module that created it, and pass the created object as one of the arguments for many of the public methods of the module.
For starters with this kind of approach to modules design you might start out with an object that has an x and y property, and then have a single method that does something to those properties such as move it by a set of given delta values for example.
This way everything is packed into a single global variable, and can be accessed from outside the the module via that single global variable. This approach works okay in some cases assuming that it is okay that everything can be accessed from outside the module, or in other words that everything is public.
There are also ways of creating an API that can be accessed from outside the module as well by assigning such an API to at least one global variable. A global can be declared from outside the function expression, or the global object can be passed as an argument to the IIFE which is another option that I see in the wild a lot. In other cases the expression can just be used to accomplish some things without polluting the global name space at all when it comes to simple projects in which everything needs to be packed into one of these. However maybe getting into all of that is a matter for another post, or at least another section in this one.
A public API can be returned in the form of an object literal when using an IIFE and a single global variable to create a module. This object literal can be the actual thing that is returned to a global variable, or it can be a variable that contains such an object that was declared elsewhere in the body of the function expression, a pattern that I tend to prefer these days.
So for a basic example of this say I have a global variable called mod, and I am using an IIFE to create a module. In the body of the IIFE I am using the return keyword to return an object literal that will function as the public API for the module in the form of a collection of methods attached as properties for the module. These public methods have access to everything that is inside the IIFE and for this example I have a point state object that can be mutated with the public methods.
lets take yet another look at making a very simple point module, this time I am not doing anything that has to do with having the a state object in the module itself, but something that is to be passed as an argument to every public method. This way I am taking the state object out of the module, and making it so that the state object is something that is create and stored in some code section that is outside of the module.
In addition to pulling the state object out of the module, I am now also using a move method that is more in line with the rules of what is often called a pure function. I will not be getting into functional programing in detail here as that is a subject for a whole other post of course. However I have found that going in the direction of functional programing helps to keep things better organized, and easier to follow and debug.