why module pattern?
I've read a lot of things about the module pattern. Ok It brings structure, private method, etc... But with the code below I can get the same behavior without using it.
function Human()
{
// private properties
var _name='';
var _age=0;
// private methods
f开发者_JS百科unction created()
{
console.log("Human "+_name+" called");
};
// public
this.setName = function(name){
_name=name;
created();
};
}
var h1 = new Human();
h1.setName("John");
So, what are the real advantage of a module pattern finally ?
I think this example could help you to clarify the usefulness of the Module Pattern.
Module Pattern
The module pattern is widely used because it provides structure and helps organize your code as it grows. Unlike other languages, JavaScript doesn’t have special syntax for packages, but the module pattern provides the tools to create self-contained decoupled pieces of code, which can be treated as black boxes of functionality and added, replaced, or removed according to the (ever-changing) requirements of the software you’re writing.
The module pattern is a combination of several patterns, namely:
- Namespaces
- Immediate functions
- Private and privileged members
- Declaring dependencies
The first step is setting up a namespace. Let’s use the namespace() function from earlier in this chapter and start an example utility module that provides useful array methods:
MYAPP.namespace('MYAPP.utilities.array');
The next step is defining the module. The pattern uses an immediate function that will provide private scope if privacy is needed. The immediate function returns an object - the actual module with its public interface, which will be available to the consumers of the module:
MYAPP.utilities.array = (function () {
return {
// todo...
};
}());
Next, let’s add some methods to the public interface:
MYAPP.utilities.array = (function () {
return {
inArray: function (needle, haystack) {
// ...
},
isArray: function (a) {
// ...
}
};
}());
Using the private scope provided by the immediate function, you can declare some private properties and methods as needed. Right at the top of the immediate function will also be the place to declare any dependencies your module might have. Following the variable declarations, you can optionally place any one-off initialization code that helps set up the module. The final result is an object returned by the immediate function that contains the public API of your module:
MYAPP.namespace('MYAPP.utilities.array');
MYAPP.utilities.array = (function () {
// dependencies
var uobj = MYAPP.utilities.object,
ulang = MYAPP.utilities.lang,
// private properties
array_string = "[object Array]",
ops = Object.prototype.toString;
// private methods
// ...
// end var
// optionally one-time init procedures
// ...
// public API
return {
inArray: function (needle, haystack) {
for (var i = 0, max = haystack.length; i < max; i += 1) {
if (haystack[i] === needle) {
return true;
}
}
},
isArray: function (a) {
return ops.call(a) === array_string;
}
// ... more methods and properties
};
}());
The module pattern is a widely used and highly recommended way to organize your code, especially as it grows.
“JavaScript Patterns, by Stoyan Stefanov (O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750
Not sure why no one's answered this one properly. I can see potential for using auto-invoking functions in some kind of pattern meant to make private vars inheritable, but you're absolutely right.
There is no benefit to using the module pattern in place of a core language function constructor. It's the same exact language mechanic (closures) that allows the persistent internal vars to exist as non-accessible entities only with more code.
In JS a function constructor follows the same rules of scope as a fired function. Scope and closure is set at point of definition. The reason the internal var from a function constructor lives on is because the instance with methods defined inside the same constructor referencing that var lives on.
The only thing that changes is that you've eliminated the use of prototyped methods on the constructor and have to jury-rig your own inheritance mechanism for inherited methods.
Huge JavaScript projects out there are getting built use module patterns, perhaps you have your own idea and want to make sure your code is easily readable and well structured. by learn a couple of patterns you could make your apps easier to build and to maintain. these patterns are used by the most JavaScript talented developers, for instance the folks build node js, JQuery, bootstrap, angular and others. Simple Example:
function foo (){
console.log("foobar");
};
foo();
when we invoke this simple method, we will notice it’s accessible in global name space, and when we talking about large application this is a huge problem.
this is sometimes we refer to it as cluttering the global name space. The reason this is a problem is because so much is happening in the browser, you might load angular, bootstrap and Jquery in the browser, you might even have a few other javascript libraries. Now if you have to navigate a bunch of variables that clutter the global name space, it could be quit a no sense. In fact it could be even a catastrophic if the variables you create share the same name as variables from another library. The most basic module pattern is going to solve this. To do this I describe my code in a self executing anonymous function, and now looks like this: From this:
function foo (){
console.log("foobar");
};
foo();
To this:
(function(){function foo (){
console.log("foobar");
};
foo();
}());
source treehouse workshop about basics module pattern in JavaScriptwe wrap a function enclosure () and then I can call it, the reason in need to wrap the function enclosure is because the function itself without a name will return undefined, however when we wrap the function parenthesis we are essentially saying treat this whole thing as an expression which is evaluated immediately and doesn’t necessarily require a naming or assignment, now when we run the code and check the browser we will see that now the global namespace isn’t clutter with my variable. We could see that foo is undefined.
I can think of 5 points using your class(like) example and the standard modular pattern.
1. Multiple Instances: Using class you can create multiple instances.
function Human() {
// private properties
var _name = 'Bob'; // Each instance will gets a new private member copy
// public for the created instance
this.setName = function (name) {
_name = name;
};
this.getName = function () {
return _name;
};
// setName() & getName() - can be moved to prototype for saving memory
}
// Instance - 1
var h1 = new Human();
h1.setName("John");
console.log(h1.getName()); // John
// Instance - 2
var h2 = new Human();
console.log(h2.getName()); // Bob (NOTE: not John)
2. Unique copy: In the above example all the members in Human() class will get a new copy (Not shared) for each newly created instances.
Let's convert the above example into Modular pattern:
var Human = (function() {
// private properties
var _name = 'Bob';
// private
setName = function (name) {
_name = name;
};
// private
getName = function () {
return _name;
};
return {
setName: setName,
getName: getName
};
})();
Human.setName('John');
console.log(Human.getName()); // John
Human.setName('Bob');
console.log(Human.getName()); // Bob
In the above modular pattern example we can't create any instance like the above class example. Here the pattern allows you to set/get the values through 'Human' in an organized way (not polluting the global scope).
Is it not possible to create a multiple instances in the modular pattern ? Yes, it is possible through constructor and prototype.
Let's add a constructor and prototype to the modular pattern:
var Human = (function () {
// private properties
var _name = 'Bob'; // Shared across all the instance
// private
setName = function (name) {
_name = name;
};
// private
getName = function () {
return _name;
};
// constructor
var Human = function () { };
// prototype
Human.prototype = {
constructor: Human,
setName: setName,
getName: getName
};
return Human;
})();
// Instance - 1
var h1 = new Human();
h1.setName("John");
console.log(h1.getName()); // John
// Instance - 2
var h2 = new Human();
console.log(h2.getName()); // John (NOTE: Not Bob bcos it uses the shared copy)
5. Shared Copy: From the above example you can see unlike a normal class, modular pattern above uses a shared private member copy for all the instances (In example point 1: Each instances will have it's own private members copy).
精彩评论