JavaScript The Module Pattern in JavaScript

How does importing another JavaScript file/library actually work?

This is a great workshop, but I'm still not exactly sure if I understand how different JavaScript files/modules are being imported. The self-invoking function below would be in a file called map.js. There are three other JS files that would be loaded in the HTML file before the map.js file.

Would the map.js function import whatever is returned from the layersModule.js, Geocoder.js, and GeoLocate.js? Do things have to be returned from those other files to be used in the map.js file?

I am trying to modalrize some map applictions to be more maintabile. I just don't fully understand how this works in practice?

Thanks for the help!

(function(){
// code that creates map
}(layersModule, Geocoder, GeoLocate));

3 Answers

Joel Kraft
STAFF
Joel Kraft
Treehouse Guest Teacher

Patrick, the module pattern, being a function, has access to any global variables that have been defined. This would include any globals layersModule.js, Geocoder.js, and GeoLocate.js have defined (I assume they defined layersModule, Geocoder and GeoLocate).

The code you included at the bottom of the post attempts to pull those global variables into the module, but the function signature (function()) provides no parameters to assign them to, so they are not provided to the module's scope by these means (though remember they are still available inside the module through the global scope). To provide them this way, you could add parameters, something like

(function(layers,coder,locate){ 
  // layers === layersModule;
  // coder === Geocoder;
  // locate === GeoLocate;
}(layersModule, Geocoder, GeoLocate));

This would create aliases for those globals inside your module: layers, coder, and locate, respectively. Again, the global names are still available, but now have a shorthand available for use as well. Outside of the module, those shorthand variable names don't exist, so they wouldn't conflict with other libraries or code present in your project.

The main use for the module pattern is to encapsulate the environment inside, and keep from polluting the global scope. Often a module will declare one global variable, an object, that contains all the functionality it wishes to expose as properties on that object.

Creating the global can be done explicitly by importing the global object into the module and assigning the module's variable as a property on that object. For example, let's say map.js wants to create a global called MyMap that provides all its functionality to other code outside the module (Note: Try to choose a variable name you know will not collide with other names. Map, for example, probably exists as a property on most js global environments.):

(function(exports){
  var MyMap = {};
  // code that augments MyMap

  exports.MyMap = MyMap
}(window));

In this example, exports contains the window (or global) variable within the module. Keep in mind that creating a global variable is the same thing as creating a property on the global object. So for example, in Chrome DevTools, this

var animal = 'giraffe';

is the same thing as this

window.animal = 'giraffe';

You can also return an object exports that represents the module you're creating, and capture it into a global variable, MyMap. The following code accomplishes the same thing as the code above:

var MyMap = (function(exports){ 
  // code that creates MyMap

  return exports;
}({}));

With this second form, you can modify it a little bit to use the "loose augmentation" pattern Huston talks about (by just adding MyMap || at the bottom.) This way if the global variable MyMap already exists, it can be added to as opposed to overwritten:

var MyMap = (function(exports){ 
  // code that creates MyMap

  return exports;
}(MyMap || {}));

There are several ways to use a module pattern. The key is to remember that in the end it's just a function that runs immediately. So it follows all the same rules that any function does.

Hope this helps, let us know if you have other questions!

Thanks Joel Kraft! This made a lot of sense. I'm going to experiment with it.

My goal is to have a web map application that is built in components, and I think I can use this module pattern to accomplish that.

Joel Kraft
Joel Kraft
Treehouse Guest Teacher

Great! Good luck. Let us know how you do!

PoJung Chen
PoJung Chen
5,856 Points

Very clearly, thanks very much!

Jesus Mendoza
MOD
Jesus Mendoza
Treehouse Moderator 22,542 Points

I know this post is pretty old but I'd give my response in case someone else is wondering the same.

module.exports and export are basically objects whose content is being created or updated when using module.exports or exports. For example:

We have the module object and that object has a property called exports.

module = {
    exports: {}
}

when we use

module.exports = {}

or

module.exports = function () {return {}; }

We are overwriting the initial property value of exports in our module object. Then when we use require, our program will search the file in the location that we passed as an argument, the file will be executed, the value of exports property in the module object is overwritten and that value will be stored in the variable we created (where we are assigning the require value to). For example:

newNameOfExportsValue var = require ( 'locationOfFile');

Now newNameOfExportsValue has the value of the property exports from the module object of our previous file.

jason chan
jason chan
30,993 Points

https://youtu.be/iDaf5UMvi1s

I did video tutorial on it. :) Nodejs for life!