I was reading about JavaScript Module pattern. My Question is how do I make submodules with it, i.e how can I inherit from it, say I have this class
var MODULE = (function () {
my = function(){
this.params = ""
},
privateVariable = 1;
my.prototype.moduleMethod = function () {
console.log("mod");
};
return my;
}());
How do I make a child class of it with properties inherited from parent? How can I do the same with module pattern?
The module pattern is not a class pattern. You cannot simply pretend you now have classes in JavaScript. As for inheritance, if you really need to inherit stuff, you should make an object via constructor function and use prototypal inheritance, although it's sometimes slower to execute.
As for creating a submodule it's simple
MODULE.submodule = (function(){
// another module stuff that can even reference MODULE
return { submodule: 'property' }
})();
Now, as for subclassing in the classical sense, you can simulate it on objects with prototypes, like Douglas Crockford does http://www.crockford.com/javascript/inheritance.html
For simulating it with modules, you can try by creating a seal/unseal functions inside the original module and use them in your submodules. You can check here http://www.pallavlaskar.com/javascript-module-pattern-in-details/
for the
Cloning and Inheritance
var MODULE_TWO = (function (old) {
var my = {},
key;
for (key in old) {
if (old.hasOwnProperty(key)) {
my[key] = old[key];
}
}
var super_moduleMethod = old.moduleMethod;
my.moduleMethod = function () {
// override method on the clone, access to super through super_moduleMethod
};
return my;
}(MODULE))
or the
Cross-File Private State
var MODULE = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
return my;
}(MODULE || {}));
> var MODULE = (function () {
> my = function(){
If my is not declared with var, it becomes global when the function executes. Also, by convention constructors have names starting with a capital letter, so:
var My = function(){
but you may as well just declare the function and be done with it:
function My() {
.
> this.params = ""
> },
> privateVariable = 1;
>
> my.prototype.moduleMethod = function () {
> console.log("mod");
> };
If you are just implementing prototype inheritance, why use the module pattern at all?
>
> return my; }());
The module pattern is not meant for inheritance but to create "modules" of functionality and emulate public, priveleged and private members to some extent.
Related
So I know that I can fix the scope of my module class below using bind as in this answer.
The only thing is that I use a slightly diffrerent syntax for my module and I am not quite sure how to apply it?
My question is then, how do I apply bind to my function correctly so that the context of this is my module?
Code:
var module = (function () {
var module = function (name) {
this.getName= function() {
return name;
}
};
module.prototype = {
something: function () {
// my function needs to access getName from here...
}
};
return module;
})();
Usage:
var foo = module('nameValue');
foo.something();
Are you sure using apply rather than bind in this case wouldn't be a better implementation?
If you just want to make the class properties available for access in a modular setup, you'll need to expose them in the class function declaration. Then they'll be available for public access using those methods.
var module = (function () {
function module (name) {
// public method exposing *name* variable with "privileged" access
this.getName= function() {
return name;
}
// publicly exposing *name* variable itself (ahh! It's naked!)
// this.name = name; // use only for read+write access to variable
};
// only setting one prototype parameter here so let's save some lines...
module.prototype.something = function () {
return this.getName(); // or
// return this.name // for direct variable exposure
};
return module;
})();
Then you can create your instances:
var mod1 = new module("bar");
var mod2 = new module("foo");
var mod3 = new module("win");
And apply a bind later on...
Though by using apply, you can do this:
var getNameOfModule = function(){ return this.getName(); }
getNameOfModule.apply(mod1); // bar
getNameOfModule.apply(mod2); // foo
getNameOfModule.apply(mod3); // win
This would depend entirely on the structure of your setup.
Also, it's good practice to start class names with a capital (as in Module vs. module).
You may want to create first an anonymous function and then set the others, and then call getName() using a self reference to the module object.
var module = function () {
var module = function(){};
module.getName = function (name) {
return name;
};
var self = module;
module.prototype.something = function () {
alert(self.getName('myName'));
};
return module;
};
var myMod = module();
myMod.prototype.something();
Here's the live example http://jsfiddle.net/ybfjB/
I've been using the Revealing Module pattern and have several namespaces.
Example:
// here's the namespace setup
var myProject= myProject|| {};
var myProject.models= myProject.models || {};
myProject.models.MyModel= function(){
var someMethod = function(){
// do something
};
return{
SomeMethod = someMethod
};
}
I'm moving to the Revealing Prototype Pattern to gain some memory usage improvements and so I can decorate the object another function. How do I keep it in my myProject.models namespace?
This gives my JavaScript errors:
var myProject.models.MyModel= function(){
// properties here
};
myProject.models.MyModel.prototype = (function(){
// methods here
var someMethod = function(){
// do something
};
return{
SomeMethod = someMethod
};
}());
You have various syntax errors.
myProject = window.myProject|| {};
myProject.models = myProject.models || {};
myProject.models.MyModel = (function () {
//declare a constructor function
function MyModel() {
}
//declare a function that will be publicly available on each MyModel instances
MyModel.prototype.someFunction = function () {
//call the private function from within the public one
//note: you have to be careful here since the context object (this) will be
//window inside somePrivateFunction
somePrivateFunction();
//call the private function and set the context object to the current model instance
//somePrivateFunction.call(this);
};
//declare a private function
function somePrivateFunction() {
}
return MyModel; //return the model constructor
})();
Now you can use your model like:
var m = new myProject.models.MyModel();
m.someFunction();
var myProject = myProject || {};
^^^
You are using a var statement here to declare the global myProject variable (if it hasn't been already), so that it will not throw Undefined variable exceptions. (Also you initialise it to an empty object if it had now value)
var myProject.models= myProject.models || {};
In here, you are assigning the models property to the object from above. The var keyword is out of place here; remove it and it will work.
With myProject.models.MyModel = … you did it right in the upper snippet and wrong in the second one; I'm not sure which you were trying to use. The revealing prototype pattern should look like this:
var myProject = myProject || {};
myProject.models = myProject.models || {};
myProject.models.MyModel = (function(){
function MyModel() {
// instance properties here
}
function someMethod(){
// do something
}
MyModel.prototype.SomeMethod = someMethod;
// ^ lowercase that?
return MyModel;
})();
is this possible?
We sure know how to emulate private members in javascript:
var Class = (function() {
var _private;
Class = function() {
_private = {};
};
Class.prototype.set = function(name, value) {
_private[name] = value;
};
Class.prototype.get = function(name) {
return _private[name];
};
return Class;
})();
The side effect of this pattern is that when I create two instances:
var instanceOne = new Class();
var instanceTwo = new Class();
then the private property is shared between:
instanceOne.set('test', 'me');
instanceTwo.get('test');
Is there some work around for this problem?
Regards
The standard way to have "private" members in JavaScript is to use local variables within the constructor and have anything that needs to access them defined as closures over the context of the call to the constructor, like this:
function Class() {
var privateValue = 0;
this.getPrivateValue = function() {
return privateValue;
};
}
Class.prototype.doSomething = function() {
// This function doesn't have access to `privateValue`
// except through `getPrivateValue`, even though
// it's accessible as a member of the instance
};
This has been described by many, probably most famously Douglas Crockford.
Note that this has the repercussion that each instance of Class gets its own copy of the getPrivateValue function, because each is a closure over a different call to the constructor (which is why it works). (This doesn't mean all the code of the function is duplicated, however; at least some engines — Google's V8 engine, used in Chrome and elsewhere for instance — allow the same code to be shared by multiple function objects which have different associated contexts.)
(Side note: I haven't used the name private because it's a reserved word. In ES3, it was a "future reserved word;" in ES5, it's only one in strict mode; details.)
I've used a simple variable above rather than an object to avoid making things look more complex than they are. Here's the way the would apply to your example:
function Class() {
var privateData = {};
this.get = function(name) {
return privateData[name];
};
this.set = function(name, value) {
privateData[name] = value;
};
}
Or if you still want to also have class-wide private data shared across instances:
var Class = function() {
var dataSharedAmongstInstances;
function Class() {
var privateDataForEachInstance = {};
this.get = function(name) {
return privateDataForEachInstance[name];
};
this.set = function(name, value) {
privateDataForEachInstance[name] = value;
};
}
return Class;
})();
Say I have the following modules, split across multiple files both capable of extending skillet:
File1.js:
(function(){
var privateVar1 = 0;
var privateFunction1 = function() {
//function definiton
};
skillet.fry() = function() {
//fry it
//matchbox.light();
};
})(window.skillet = window.skillet || {});
File2.js:
(function(){
var privateVar2 = 0;
var privateFunction2 = function() {
//some private function
};
skillet.grillIt = function() {
//grill It
//matchbox.strike(); <-- Shared with File1.js
};
})(window.skillet = window.skillet || {});
Is it possible to have a shared variable/object like matchbox be sharable by the two modules without being bound to window.matchbox or window.skillet.matchbox? I.e. the visibility of matchbox should only be to File1.js and File2.js and must not be accessible elsewhere. I doubt if it's possible, but is there a way to achieve such a behavior in JavaScript? If not, what's the best practice to use in this regard?
(It's more like having a shared event-bus among a set of related modules without exposing that bus globally)
Nope.
"private" variables work in JS only because of the scope that the function was declared in. There is no way to share that scope with a function declared in an entirely different scope. Scope is an unchangeable property of functions, once they are created.
This is why this sort of thing is usually done with _foo style properties.
skillet._matchbox = { strike: function() { ... } };
The underscore prefix is convention for "internal" and serves as a hint not to mess with it.
You could also get creative with how you pass matchbox around though, though in all cases it will mean providing a way to get matchbox out it's original scope. Like perhaps, makes a skillet.extend method that passes the matchbox to it's argument?
(function() {
var matchbox = { strike: function() { ... } }
window.skillet = {
extend: function(fn) {
fn(matchbox);
}
};
})();
skillet.extend(function(matchbox) {
var privateVar2 = 0;
var privateFunction2 = function() {};
skillet.grillIt = function() {
//grill It
matchbox.strike();
};
}
Which allows you to use matchbox outside it's original scope in a controlled way. But it also allows anyone to get matchbox that maybe shouldn't.
var stolenMatchbox;
skillet.extend(function(matchbox) {
stolenMatchbox = matchbox;
});
while (stolenMatchbox.count > 0) { stolenMatchbox.strike(); }
alert("Now you are outta matches, sucker!");
Since you are already dividing your code into multiple files, you may look into using a module loader like require.js. You could define a third module for the matchbox and then pass it in as an argument to the two skillets in your example above. With this approach, you won't have to globally expose the matchbox via the window.
File1.js with require.js would look like this:
define(['matchbox'], function(matchbox){
(function(){
var privateVar1 = 0;
var privateFunction1 = function() {
//function definiton
};
skillet.fry() = function() {
//fry it
matchbox.light();
};
})(window.skillet = window.skillet || {});
});
matchbox.js would look something like this:
define([], function() {
function light() {
//light implementation
}
function strike() {
//strike implementation
}
return {
light: light,
strike: strike
}
}
I want to access variables by using
MyNamespace.variable1
that are globally accessible. I believe Drupal does something similar, no?
var MyNamespace = {};
MyNamespace.variable1 = value1;
It's just an object really.
What Drupal does is using the following code:
var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'locale': {} };
Drupal.attachBehaviors = function (context, settings) {
context = context || document;
settings = settings || Drupal.settings;
// Execute all of them.
$.each(Drupal.behaviors, function () {
if ($.isFunction(this.attach)) {
this.attach(context, settings);
}
});
};
Drupal.detachBehaviors = function (context, settings, trigger) {
context = context || document;
settings = settings || Drupal.settings;
trigger = trigger || 'unload';
// Execute all of them.
$.each(Drupal.behaviors, function () {
if ($.isFunction(this.detach)) {
this.detach(context, settings, trigger);
}
});
};
// …
Using similar code, you can emulate namespaces using JavaScript.
Also, if you have many JS files that each add a "namespace" or Object into a top level package you can do stuff like this:
ModuleA.js
// if Modules is null, create a new object, else use the currently defined instance
var Modules = Modules || {};
Modules.A = {};
// sample instance variable
Modules.A.instanceVar;
// sample function
Modules.A.myFunc = function(param1, param2) {
// do something
}
ModuleB.js
// if Modules is null, create a new object, else use the currently defined instance
var Modules = Modules || {};
Modules.B = {};
// sample instance variable
Modules.B.instanceVar;
// sample function
Modules.B.myFunc = function(param1, param2) {
// do something
}
Then you can of course just call them as you need them Modules.A.myFunc() or Modules.B.myFunc() or Modules.B.instnaceVar = 20;. So you can encapsulate functions as well as variables.
For my code I like to have a root Object, (i.e ) and then added "classes" (objects) to it so that everything has a nice "package like", "OOP" structure to it.
Just create an object. E.g.:
var MyNamespace = {};
MyNamespace.variable1 = ...