Javascript modules are a design pattern that allow you to encapsulate your code into smaller self managing pieces. They help you separate your code, protect your variables, and provide an easy way to expose only the parts of your component that you want to be exposed.
[00:00] The JavaScript module pattern's a great way to bring some encapsulation into your code. If we look at this basic calculator here, we have some simple arithmetic functions going on. Our HTML really doesn't have anything in it. We're bringing in a couple script files, calc and calc module.
[00:16] Let's take a look at calc, that's where most of the logic is. You can see that we have add, subtract, divide. We've got an input function that is processing all of the user button clicks and that's our calculator.
[00:29] Now, we're going to show you why you want to use the module pattern in your code. Let's say that you have a variable current total and someone else declares that same variable in a different file. Those two variables are now competing with each other with one clobbering the other.
[00:45] To see this, let's refresh the page and use our calculator. We can see that we had a hidden serving value of 77 that was set by our other file. The variables used by the calculator are no longer safe, so we're going to show you how to protect those variables using the module pattern.
[01:00] The first step we need to do is create a function. We're going to call ours Magic Calculator, and then we're going to take a look at it here in the Chrome debugger. As we go refresh this and we look, we can see the type is function and there's nothing really on it.
[01:17] Our next step is to wrap our function in parentheses and add some invoking parentheses at the end of the function, as well.
[01:26] If we go take a look at that in the Chrome debugger, it's still going to be a function with nothing on it, and so we're, we've got one more piece to add in here. We're going to create a variable called Inner Calc to some object and we're going to return that object.
[01:44] Now, if we go refresh the page and we look at it, our Magic Calculator is an object, and that's because this follows the IIFE pattern, or immediately invoke function expression. You can see if we add this something variable, we are, it's on our object, which means that our function, our Magic Calculator has been invoked and we have the return value. We are no longer storing the function itself.
[02:12] The next thing we need to do to get this working is a little cut and paste magic. We're just going to grab this bit of code from calc JS and we're going to paste it straight into our calc module. We refresh the page and our Magic Calculator, if we take a look at it, we cannot see any of the variables or functions that we copy pasted over.
[02:39] But we do want to expose the input function. It's something that we need to use externally, so we're going to put it on that inner calc object that we created, instead of declaring it as a function directly. Now that calc element here can access the input function.
[02:59] If we look at it, you can see the input function right there on the calculator in the watch. Then if we go to use it, oops, we've got an exception here, because we haven't actually called the input function on the Magic Calculator. We moved it over and then we didn't update our invocation.
[03:17] Now, we've got the calculator working. Our numbers are arithmeticking as we expect. But we've got a problem here, the update result function, it lives over in calc JS and we're accessing it. That's a really bad pattern.
[03:31] To fix it, we're going to create this set listener function on our Magic Calculator over in our module. We're just going to store a pointer to a listener that gets passed in. We're going to go, let's go up to the top of the file here and add that in.
[03:53] Now we have a pointer to that listener and we're going to take where we were before calling update result, we're now going to call the pointer that was given to us and just to be safe, we're going to wrap that with an if statement to make sure that we actually have one. Because set listeners called externally, we can't guarantee that we're going to have what we want. We'll copy paste that down there real quick, as well, for safety.
[04:15] All right, let's give this a try and it's not working because we didn't actually call that set listener function that we had set up. Let's go back over here by our jQuery, we're going to pass in our original update result function that knows how to update the element on the screen, and now we've got a working module.
[04:36] Key points here are that we want to wrap a function in parentheses and add invoking parentheses, and then create an inner object that we're going to return. As soon as we do that, any variables or functions that we create directly inside of the wrap function are effectively private and inaccessible to the rest of JavaScript. Whereas, anything that we've placed directly on the inner object can be accessed publicly or outside of our module through the captured variable.