[JS #2 WIL Post]
Encapsulation is not inherent in Javascript. There are no modifiers like private
and public
to help protect objects from unwanted access. This is one reason why function scope is important in JS. Each function creates a new scope. The scope dictates the visibility of the variables inside a function.
For example in the snippet below, the gridItems
attribute of the gameboard cannot be accessed directly unless the getter/setter method is used. Thus, the possibility of setting incorrect grid item values will be removed.
Note that the checking of row, column, diagonal winners of the game board is not accessible from the objects that will be importing it. Only the returned functions of GameBoard
will be accessible outside it.
const GameBoard = (function() {
//no one can access this variable directly
let gridItems = Array(9).fill('I');
function resetBoard() {
gridItems = Array(9).fill('I');
}
function setGridItemValue(index) {
gridItems[index] = turn;
}
function getGridItems() {
return gridItems.slice(0);
}
function checkWinner(board) {
if(checkDraw(board)) {
return "tie";
}
if(checkRowWin(board) ||
checkColumnWin(board) ||
checkDiagonalWin(board)) {
return winner;
}
return null;
}
...
return {
setGridItemValue,
checkWinner,
resetBoard,
getGridItems,
}
}());
One more important thing to note about this pattern aside from encapsulation is its use of IIFE (immediately invoked function expressions). It is run as soon as it is defined. It is sometimes called a self-executing anonymous function and has two parts:
A. The function itself with the Grouping operator
(function () {
statements
})
B. The second one creates the IIFE ()
through which the JS engine will directly interpret the function.
The second part makes sure that there is no accidental invocation of the function, thus creating a lot of GameBoard objects. To use the GameBoard, the user can just call the publicly available functions, i.e,
GameBoard.resetBoard();
GameBoard.checkWinner();
Now, the GameBoard module can be used in other parts of the JS projects. Check the usage of the GameBoard
function in this repository.
References
[1] Revealing Module Pattern
[2] IIFE
Top comments (4)
Just thinking out aloud ...
I was wondering what the difference between the module pattern and the revealing module pattern was.
Addy Osmani documented both in 2012 attributing the module pattern to Richard Cornford (2003) and the revealing module pattern to Chris Heilmann (2007).
Using an IIFE to create a closure that the object methods could use to share private data was already part of the "classic" module pattern:
The problem with the classic module pattern is that you have to use the outside variable (here
counter
) to reference a public method within any other object method.One way to get around this is to use
this
:But around this time people were trying to avoid
this
as much as possible. So the revealing module pattern gets rid of intermediate references through the object by only using standalone functions that reference one another or shared data directly within the closure. Only those functions that are to be revealed to the public are attached as function values to the object literal that is returned.So the revealing module pattern isn't returning an object in the conventional sense but a "map" of non-method function values that access one another and shared data through the closure they were created in.
Just in case anybody was curious.
Wow thank you for this peerreynders!!
... come to think of it, as there is no reliance on
this
, the return value doesn't have to be an object anymore.Though perhaps now we aren't revealing a "module" anymore.
definitely a good read Patricia :)