Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2017
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.36 KB | None | 0 0
  1. # The Revealing Module Pattern in Javascript
  2. > Zach Caceres
  3.  
  4. Javascript does not have the typical 'private' and 'public' specifiers of more traditional object oriented languages like C# or Java. However, you achieve the same effect through the clever application of Javascript's function-level scoping. The Revealing Module pattern is a design pattern for Javascript applications that elegantly solves this problem.
  5.  
  6. The central principle of the Revealing Module pattern is that all functionality and variables should be hidden *unless deliberately exposed*.
  7.  
  8. Let's imagine we have a music application where a musicPlayer.js file handles much of our user's experience. We need to access some methods, but shouldn't be able to mess with others.
  9.  
  10. #### Using Function Scope to Create Public and Private Methods
  11.  
  12. Let's first see how Javascript's function-level scope can help us create public and private methods.
  13.  
  14. All functionality is moved to a function's scope. Then we return an object with the functions that you'd like accessible in other files.
  15.  
  16. ```js
  17. // musicPlayerModule.js
  18.  
  19. var musicPlayer = function () {
  20. // Let's make sure no one can directly access our songList
  21. var songList = ['California Girls', 'California Dreaming', 'Hotel California'];
  22.  
  23. // We'll expose all these functions to the user
  24. function play () {
  25. console.log('Im playing the next song!');
  26. }
  27.  
  28. function pause () {
  29. console.log('Im paused!');
  30. }
  31.  
  32. function addTrackToMusicQueue (track) {
  33. songList.push(track);
  34. console.log('I added a song');
  35. }
  36.  
  37. function showNextTrack () {
  38. console.log('My next track is', songList[0]);
  39. }
  40.  
  41. // Let's hide this function
  42. function loadSong() {
  43. filesystem.loadNextSong();
  44. }
  45.  
  46. return {
  47. playMusic: play,
  48. pauseMusic: pause,
  49. showUpNext: showNextTrack,
  50. addTrack: addTrackToMusicQueue
  51. }
  52. }
  53.  
  54. const musicModule = musicPlayer(); // invoke our musicPlayer to return it's object (module)
  55. musicModule.playMusic(); // 'Im playing the next song!'
  56. musicModule.pauseMusic(); // 'I'm paused!'
  57. musicModule.showUpNext(); // 'The next track is California Girls'
  58. musicModule.loadSong(); // error: not a function
  59. musicModule.songList.push('White Rabbit'); // undefined
  60. ```
  61.  
  62. Now we can access all the methods that we need on our `musicModule` object. But we can't fiddle with our `songList` or access the `loadSong()` method. These are both private.
  63.  
  64. This works fine. But there's one big problem.
  65.  
  66. We're using `musicPlayer` as a namespace to hold our functions. But wait, our `musicPlayer` is a function that's still exposed to the global scope!
  67.  
  68. Someone could come along and invoke it again, creating a new `musicPlayer` and all sorts of problems.
  69.  
  70. #### Hiding Your Module with an Anonymous Function
  71. The best way to avoid exposing your top-level function to the global scope is to wrap everything in an anonymous function.
  72.  
  73. This anonymous function is immediately invoked when the file is run. Since the function is anonymous, it can never be invoked elsewhere.
  74.  
  75. Here's how that looks:
  76.  
  77. ```js
  78. var musicModule = (function () {
  79. // Let's make sure no one can directly access our songList
  80. var songList = ['California Girls', 'California Dreaming', 'Hotel California'];
  81.  
  82. // We'll expose all these functions to the user
  83. function play () {
  84. console.log('Im playing the next song!');
  85. }
  86.  
  87. function pause () {
  88. console.log('Im paused!');
  89. }
  90.  
  91. function addTrackToMusicQueue (track) {
  92. songList.push(track);
  93. console.log('I added a song');
  94. }
  95.  
  96. function showNextTrack () {
  97. console.log('My next track is', songList[0]);
  98. }
  99.  
  100. // Let's hide this function
  101. function loadSong() {
  102. filesystem.loadNextSong();
  103. }
  104.  
  105. return {
  106. playMusic: play,
  107. pauseMusic: pause,
  108. showUpNext: showNextTrack,
  109. addTrack: addTrackToMusicQueue
  110. }
  111. })(); // our anonymous function is invoked here
  112.  
  113. musicModule.playMusic(); // 'Im playing the next song!'
  114. musicModule.pauseMusic(); // 'I'm paused!'
  115. musicModule.showUpNext(); // 'The next track is California Girls'
  116. musicModule.loadSong(); // error: not a function
  117. musicModule.songList.push('White Rabbit'); // undefined
  118. ```
  119.  
  120. Our function-level scope still keeps our methods and variables public and private based on whether we expose them in the return object.
  121.  
  122. But this time, we avoid the risk that we can invoke our module elsewhere in the code.
  123.  
  124. In other files we can now use `musicModule`'s' functionality – a well-encapsulated module in our global scope!
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement