After taking a short break during the holidays, I'm happy to be back with a new post. This time, we'll be taking a look at a Revealing Module Pattern, frequently used by JavaScript developers.
It's a very useful pattern that keeps our codebase clean and prevents malicious JavaScript manipulation from the browser console. Both junior and senior JavaScript developers are not usually aware of this pattern and it can be really useful for both performance and security.
I'm very fond of this pattern and I'm using it all the time when working on non-React projects.
About the window object
JavaScript's window
object represents the browser window. Sounds simple enough. Like any object, it contains properties (variables) and methods (functions).
For example, some of the window properties are:
window.innerHeight
- inner height of the browser window
window.innerWidth
- inner width of the browser window
And some of the window methods are:
window.alert()
- opens a popup window with a message
window.open()
- opens a new window
window.close()
- closes the current window
What's special about the window object is that it's globally accessible in most cases. Properties and methods of the objects can be accessed from any file that supports client-side JavaScript... and they can be accessed even from your regular browser via the dev tools.
Potential issues with the window object
Malicious code manipulation
Try defining a JavaScript file that contains only the following line:
let score = 0;
const updateScore = (newScore) => score = newScore;
It looks like a regular JavaScript, right? No apparent issues can be seen.
If you open this website in your browser, you can see the score
variable included in the window
object. Meaning that you can freely manipulate the variable directly from dev tools in your browser! If this variable is crucial to the site's functionality or it contains sensitive information, it can be easily accessed and exploited.
The same rule applies to methods (function). Any function present in the window
object can be called from the dev tools.
Performance & Garbage collection
You might have come across the advice along the lines of: Avoid polluting the global namespace. This basically means that we should avoid declaring global variables and functions. What is the reason for that?
Garbage collection means that the browser automatically manages memory by deciding which resources are needed at that moment. When a function or a variable is no longer needed, the browser frees up space. If all our variables and functions are part of a global window
object, the browser automatically assumes that these are needed as long as the window (or a tab) is opened, so they will never be removed. The memory will always be allocated for those resources regardless of the fact if they are actually used. That is why we refer to this as garbage and pollution in terms of the code.
Public and private scope
Javascript doesn't really have the usual public or private scope modifiers like the regular Object-oriented languages do. We can solve this in a really elegant and simple way by using JavaScript's regular function-level scoping.
Revealing module pattern
This is where Revealing module pattern Javascript comes in. Let's take a look at the following example.
const game = (() => {
let score = 0;
const setScore = (newScore) => score = newScore;
const incrementScore = () => setScore(score + 1);
return {
incrementScore
}
})();
We can see how Revealing module pattern lives up to its name.
const example = (() => {
/* Variable and function definitions */
return {
/* Variables and functions that we would like to expose */
}
})();
All variables and functions that are not returned are considered private and cannot be accessed outside the scope of the function.
By returning an object that can contain any variables and functions declared in the IIFE (immediately-invoked function expression, which is explained later) we are choosing what parts of the functionality to reveal. These cannot be altered from the global scope. In a worst-case scenario, manipulation would cause the functionality to fail and the site would break on the client's side, but that is also true for any other kind of code manipulation that we can do from our browser's dev tools (HTML, CSS or JavaScript manipulation).
In our example, we have the following private elements:
-
score
- a variable that keeps track of the current score value -
setScore
- a function that directly manipulates thescore
variable by setting its value directly. Also known as a setter function.
Those two functionalities are very important in our example and should not be accessed outside the function, so we need a create an interface that we can reveal that will update the score
variable indirectly.
This is where the incrementScore
function comes in. It only calls the private function and determines how the score should be incremented. Thusly, this functionality cannot be altered or manipulated in a malicious way beyond simply breaking the website on the client's side.
And, finally, by wrapping our game
expression in the IIFE (immediately-invoked function expression), we prevent the function from being included in the window object
and we avoid the possibility of someone to initialize another game
from dev tools.
Now that we understand how Revealing Module Pattern works and how it can be implemented, let's go through an example.
Example
Let's imagine that we are working on a game and our task is to create a score tracking function that has the following functionality:
- Initialize the score tracking with value of 0
- Allows us to increment the score by 1 (rule of the game)
- Resets the score
- Submits the current score once the game is finished
- Displays score state in HTML
window object implementation
Let's first implement this in a "regular way" just to get a better grasp of the functions and highlight the potential issues that we've explained.
Note: You might want to open this codepen link in a window to use the Console functionality in order to try and manipulate the score.
Let's see if we are able to manipulate the score from the browser's dev tools.
As expected, we can easily access and manipulate the score value and call any function that we want.
Revealing module pattern implementation
Let's convert our JavaScript implementation into a Revealing module pattern. We can easily determine which parts of the interface need to be revealed by looking at which functions are being directly called from the HTML.
Let's see if we are now able to manipulate the score from the browser's dev tools.
We have successfully removed our functionality and variables from the window
object and we've prevented the possibility of manipulating the values in a malicious way.
We could have also taken a look into how to better protect the incrementScore
function so the user cannot call it from the dev tools, but that would make this example a bit more complex than it needs to be. Also, this function is only revealed so it can be connected to a button for convenience. We could imagine that this would be tied into game mechanics which would also remain private functions.
These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.
Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.
Top comments (1)
Thank you! This was super useful. I specially love the inclusion of both examples, it helps me a lot.