置頂 0%

Revealing Module Pattern (JS)

前言

看到在 stackoverflow 有人發問 why do I need to return “init” to execute init function? ,這是一個關於JS的design pattern的問題,其實我之前在其他地方就有看過類似的寫法,只是不知道它的一些概念和目的,因此這篇就來記錄一下這種設計模式的筆記。

下面的code是網友發問貼上來的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var test = function(){
console.log("kick off");
var insideTest = "variable inside test";
var init = function(){
var insideInit ="variable inside init";
console.log("inside init");
}
return{
init:init
}
}
test().init(); // exposing the private function
// ====Console====
// kick off
// inside init

主要是發問說為何不能直接呼叫test().init(),而一定要加上return inint:init,才能得到正確的結果。其實回答的網友就直接提到這是一個Revealing Module Pattern,另外說明因為function init是寫在function test裡面,所以init的存取權限就只限於test裡面,只要超出test的範圍(scope)就會存取不到(undefined),所以才要在函式的最後加上return init:init;這一段,讓外部的範圍可以來存取到這一方法,其實就是間接達到Java中的封裝效果,讓外部範圍只能透過你所提供的公開方法來存取,像是給函式init加上Private一樣。其實標準習慣的方式會直接宣告function()那邊加上括號,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
var test = (function(){
console.log("kick off");
var insideTest = "variable inside test";
var init = function(){
var insideInit ="variable inside init";
console.log("inside init");
}
return{
init:init
}
})();
console.log(typeof(test)); //object
test.init();

這自動執行function並回傳,所以test會直接是一個物件,而不是一個函式,如此可以省去呼叫test時候還要加上()。下面將來紀錄這種設計模式的範例

Module Pattern

透過閉包(closure)的特性(變數或函式可以存取的範圍),來實作出一種可以呼叫的公共(public) 函式,同時能夠封裝私有成員的方法,滿足我們想要隱藏一些商業邏輯及讓程式碼更具結構化,下面則是以上面的例子來修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var test = (function(){
// private variable
var insideTest = "variable inside test";
// private function
var init = function(){
var insideInit ="variable inside init";
console.log("inside init");
}
// 回傳一個object
return{
//public function
getInsideTest: function() {
return insideTest;
},
setInsideTest: function() {
insideTest = insideTest;
}
}
})();
test.setInsideTest('akb48');
console.log(test.getInsideTest()); //akb48

Revealing Module Pattern

揭示模組模式(Revealing Module Pattern)則是上面Module Pattern的改良版本,其實就是把所有函式或變數都在閉包中定義,返回值是不包含任何定義,提高程式碼的可讀性及結構性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var test = (function(){
// private variable
var insideTest = "variable inside test";
// private function
var setInsideTest = function() {
insideTest = insideTest;
}
var getInsideTest = function() {
return insideTest;
}
// Return an object literal with no function definitions
return{
getInsideTest: getInsideTest,
setInsideTest: setInsideTest
}
})();
test.setInsideTest('tpe48');
console.log(test.getInsideTest()); //tpe48

參考

  1. https://medium.com/@Rahulx1/revealing-module-pattern-tips-e3442d4e352
  2. https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch09s03.html
  3. http://www.tastones.com/zh-tw/stackoverflow/javascript/creational-design-patterns/module_and_revealing_module_patterns/