forked from stevekwan/experiments
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodule-pattern.html
More file actions
145 lines (118 loc) · 5.33 KB
/
module-pattern.html
File metadata and controls
145 lines (118 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<!DOCTYPE html>
<html>
<!--
An exploration of the Module Pattern, a useful method for encapsulation in
JavaScript.
If you want to learn more about JavaScript and "the right way" to write it,
read The Good Parts, by Douglas Crockford. I can't recommend it enough.
http://shop.oreilly.com/product/9780596517748.do
Note that this is NOT the only way to implement the Module Pattern. It is,
however, my favorite way. I prefer it because it's simple to implement,
easy to read, and avoids a lot of the JavaScript-specific concepts that
trip up developers unfamiliar with the language.
Enjoy!
Author:
Steve Kwan
mail@stevekwan.com
http://www.stevekwan.com/
Originally from my GitHub:
https://github.com/stevekwan/experiments/
Date: Feb 21, 2013
-->
<head>
</head>
<body>
<script>
// The module pattern is a good way to encapsulate your JavaScript functions
// and properties. The example below shows how to create a module, namespace
// it, and specify public/private properties and functions.
// Be aware that the Module Pattern is NOT generally used for object-oriented
// programming. It does not give you the ability to define a class that can
// spawn objects based on its definition. Although it is possible to jerry
// rig the Module Pattern to define classes, there isn't a real benefit to
// doing this as JavaScript has another facility for this.
// If you are more interested in laying out a classical object-oriented
// hierarchy, look at this example instead:
// https://github.com/stevekwan/experiments/blob/master/javascript/class.html
// However, be aware that JavaScript is not a classically object-oriented
// language. If you are trying to write true classical OOP in JavaScript,
// you're probably doing it wrong. :)
// Advantages of the Module Pattern:
// -Avoids nonsense with the "this" keyword, which often causes confusion
// -Gives you basic encapsulation without having to write a lot of code
// -If you are creating a singleton "class," the Module Pattern is for you.
// Disadvantages of the Module Pattern:
// -True class-based OOP doesn't work well with the Module Pattern.
// First, let's create a namespace. It's not required, but it's usually a
// good idea.
var MyNamespace = MyNamespace || {};
// Let's add our module to the namespace. Basically, it's just a property of
// the namespace. Note that our module is actually a function. We're going
// to use JavaScript closures to emulate private methods, which are not
// natively part of JavaScript.
MyNamespace.MyModule = function()
{
// Let's define a private and public property. Note that we define them in
// exactly the same way. The bit that specifies whether they are
// public/private comes later...
var myPrivateProperty = 2;
var myPublicProperty = 1;
// Let's declare a simple private function.
var myPrivateFunction = function()
{
console.log("myPrivateFunction()");
};
// Now let's declare a public function. Again, note that the function
// definition is exactly the same as the private one.
var myPublicFunction = function()
{
console.log("myPublicFunction()");
// Just for fun, let's call our private function. Note that while we are
// inside the module, we have full access to all Module properties and
// functions, just like if we were inside a class.
myPrivateFunction();
};
// Let's make a setup function for this module: something that is called
// once when it's loaded. I generally like to call my setup functions
// init().
var init = function()
{
// Do some setup stuff
console.log("init()");
};
// This is the part that separates the private and public stuff. Anything
// in this object becomes public. Anything NOT in this object becomes
// private.
var oPublic =
{
init: init,
myPublicProperty: myPublicProperty,
myPublicFunction: myPublicFunction
};
return oPublic;
}();
// This is the interesting part: we are returning our oPublic interface, and
// immediately invoking our MyModule function with the () at the end.
// We do this because we are not actually saving the function we created; we
// are saving the RESULT of the function. The () makes us immediately call
// the function, and it is the result we save. The original function itself
// is discarded...but its contents live on via JavaScript closures!
// MyModule is not the function we have defined; rather, it is the result of
// an anonymous function that was called once and discarded. Because that
// function doesn't have a name, we can't refer to its internal properties
// directly. And that's why the properties NOT in the oPublic interface
// become private. :)
// Let's call our setup function....
console.log("Calling init()...");
MyNamespace.MyModule.init();
// And our public function. Internally, this will call myPrivateFunction.
// This wil work because it's being called from inside the module.
console.log("Calling myPublicFunction()...");
MyNamespace.MyModule.myPublicFunction();
// This will throw an error because myPrivateFunction() is not accessible
// from outside the module.
console.log("Calling myPrivateFunction()...");
MyNamespace.MyModule.myPrivateFunction();
</script>
</body>
</html>