YDKJS - book 2, chapter 5 scope and closures. Modules and 'modern modules'

At the very end of the chapter the author discusses modules and ‘modern modules’. I am able to follow the examples and I do understand mostly how the results are achieved but I really don’t get the underlying logic of what exactly a module is. The examples are so odd that I can’t figure out why or how you would use one in the real world. Can anyone help explain this a bit better or point me in the direction of a resource that might explain it better? Also, in the return function for these module examples, there is an object with some key:value pairs that where the key and value are always the same. ex.

function define(){…}

function get(){…}

return {
define: define
get : get
}

Does this mean that the value of define in this property would get the result of calling the define function and then return that as the public API? If so, why wouldn’t it be ‘define: define()’?

Any help is appreciated!

The idea of a module is to encapsulate functionality and make “private” data and functions specific to that module which other parts of the could do not/should not have access to. This keeps things clean from an environment standpoint (why clutter your environment with variables/function names which are not needed outside of the scope of this bit of functionality? It’s messy and confusing to do so …)

In the return portion, the module initialization code returns an object composed of references to functions and/or values that it does want to be publicly available to other modules/code.

In your example, the reason is isn’t …

return {
   define: define()
};

Is because in that case you would be returning the results of define … when what you want to return is the reference to the function itself so that function can be called at a later time (perhaps with unique inputs - I haven’t seen the example code so I don’t know what the author was actually demonstrating).

The function references returned during initialization will have access to all other variables/functions in scope when they were defined, allowing publicly returned function references to have access to privately defined variables/data/functions.

Here is an example for a module I’m looking at right now. This is a module for allowing a user to order an image as a photographic print …

IMAGES.order = ( () => {
	
	function addCrop( options, $controls ){}
	
        // THIS IS A "MODULE" INSIDE THE MODULE ...
	const addToOrder = (() => {})();
	
	const bind = (() => {})();
	
	function remove( options, $container ){}
	
	function show( options ){}
	
	function showHelp(){}
	
	function unbind( $controls ){}
	
	function updateInterfaceText( $controls ){}
	
	const config = {};
	
	return { show };
	
})();

There are 8 functions, but only one of them is public - show.

I don’t return { show() }; as that would execute the show function (which is a function that shows the UI and which expects an options object). Instead, I return { show }; a reference to the show function. Now external code can call IMAGES.order.show() to display the UI for ordering an image.

The module manages all of its own data and uses the functions like addCrop(), addToOrder(), etc. internally - no external code needs to call those. The show function, which is public, has access to all of the private functions like bind/unbind, showHelp, etc.

Anyway, I hope that helps!

Regards,
Micheal

4 Likes

Thank you Michael, this was exactly the explanation I needed! The returned ‘reference’ was the part that was screwing me up - I thought it was returning the function result rather that just a reference to the inner function. Thanks again!