Javascript mixins when using the module pattern - javascript
I've been using the module pattern for a while, but recently have started wanting to mix in functions and properties into them to increase code re-use. I've read some good resources on the subject, but still am a bit uncertain as to the best approach. Here is a module:
var myModule = function () {
var privateConfigVar = "Private!";
//"constructor"
function module() {}
module.publicMethod = function () {
console.log('public');
}
function privateMethod1() {
console.log('private');
}
return module;
}
And here is a mixin object:
var myMixin = function () {};
Mixin.prototype = {
mixinMethod1: function () {
console.log('mixin private 1');
},
mixinMethod2: function () {
console.log('mixin private 2');
}
};
Ideally, I'd like to mix-in some methods from other objects as private methods and some as public methods, so that I could call some "extend" function, with a param as "private"/"public". So, that
mixin(myModule, myMixin, "private");
makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope, and:
mixin(myModule, myMixin, "public");
makes the myMixin methods available within myModule by calling module.mixinMethod1() and have correct scope
I've tried using a method that copies properties from one prototype to another, I've tried the underscore extend method to copy properties of the object from one to to the other, and various things in between. I think I'm a bit turned around regarding scope and prototypes at this point, and would love some direction as to how best to do mixins like this when using the module pattern. Note that it doesn't matter what the object myMixin looks like (whether adding functions to the prototype, or a module itself), I'm just trying to figure out some way to make it work.
Thank!
So that [some code] makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope
That's impossible. You cannot modify a scope by calling a function, especially not from outside. See also Is it possible to import variables in JavaScript? for the design reasons of that.
So, what can you do?
From outside the module
Nothing to the private scope(s) of module functions. And you cannot use the private functions of the module, obviously. You can extend its prototype with methods (which is the most common), you can even decorate its constructor function. Within those, you can use your own private functions, either completely static ones or class-specific ones.
var myMixin = (function() {
// everything class-unspecific but mixin-local
var staticMixinVariables, …;
function globalPrivateFunction(){…}
function staticMethod(){…}
return function(mod) {
// everything class-specific
// also using the locals from above
mod.staticHelper = function() { staticMixinVariable … };
mod.prototype.mixinMethod1 = staticMethod;
mod.prototype.mixinMethod2 = function(){…};
…
};
})();
// Example:
myMixin(SomeClass)
From within the module
Using the mixin in the module code itself can allow for much greater flexibility.
var myMixin = (function() {
// everything class-unspecific but mixin-local
…
return {
publicHelper1: function(){…},
publicHelper2: function(){…},
decorateInstance: function(o) {
o.xy = …;
},
extendPrototype: function(proto) {
// everything class-specific
// also using the locals from above
proto.mixinMethod1 = staticMethod;
proto.mixinMethod2 = function(){…};
…
}
};
})();
With such an interface, it becomes easy to construct a class that is using this as a mixin (not inheriting from it):
var myClass = (function() {
function Constructor() {
myMixin.decorateInstance(this);
…
}
Constructor.prototype.method1 = function() { myMixin.publicHelper1() … };
Constructor.prototype.method2 = function() { … };
myMixin.extendPrototype(Constructor.prototype);
Constructor.myHelper = myMixin.publicHelper2; // re-export explicitly
return Constructor;
})();
However, the mixin will never have access to the private class variables, nor can it present a private, class-specific API. Still, we can use dependency injection to provide that access explicitly (and having a mixin factory in effect):
var myClass = (function() {
var … // private class functions and variables
var mixer = myMixin(privateClassHelper,
privateClassVariable,
function setPrivateVar(x) {…},
… );
var myHelper = mixer.customHelper, … // local "aliases"
function Constructor(localX) {
mixer.decorateInstance(this, localX);
…
}
… // further using the class-specific private mixer
return Constructor;
})();
Not all techniques shown above need to be used in every mixin, just choose the ones you need. Not all possible techniques are shown in the above examples, also :-) The mixin pattern can be applied onto a plain module or inside its declaration as well, the above examples have only shown classes with prototypes.
For a few good examples, and a theoretical distinction between (stateless) Traits, (stateful) Mixins and their "privileged" counterparts, have a look at this presentation.
The with keyword can be very usefull to define a scope, but it has also some drawbacks (it is by the way forbidden in strict mode).
Using the with keyword, you can define a private variable privateScope within the body of your module, that would contain all your provate methods :
var myModule = function () {
var privateConfigVar = "Private!";
var privateScope = {};
//"constructor"
function module() {}
var proto = module.prototype;//avoids multiple attribute lookup
//Let's re-define you example' private method, but with a new strategy
privateScope['privateMethod1'] = function() {
console.log('private');
}
proto.publicMethod = function () {
with(privateScope){
//this call should work
privateMethod1();
}
console.log('public');
}
proto.publicMethod2=function(name,fn){
with(privateScope){
//this will be defined later by a Mixin
otherPrivateMethod();
}
console.log('public2');
}
proto.definePrivateFunction=function(name,fn){
privateScope[name] = fn;
}
return module;
}
Your mixin will use the definePrivateFunction we just defined to add private methods to the private scope :
//An example mixin implementation
function Mixin(source,target,flag){
if(flag==="private"){
for(var currentMethodName in source){
target.definePrivateFunction(currentMethodName,source[currentMethod])
}
}else{
for(var currentMethodName in source){
target[currentMethodName]=source[currentMethod];
}
}
}
The following code should work fine:
var test = myModule();
var testInstance = new test();
testInstance.publicMethod();// will call the private method defined internally
Mixin({
otherPrivateMethod:function(){
console.log("other Prvate Method called")
}
},test.prototype,"private");
testInstance.publicMethod2();// will call the private method defined by the mixin
Ideally, I'd like to mix-in some methods from other objects as private methods and some as public methods, so that I could call some "extend" function, with a param as "private"/"public". ...
As it already has been mentioned, there is no way of achieving exactly this goal.
So, that ... makes the myMixin methods available within myModule by just calling mixinMethod1() and have correct scope, and: ... makes the myMixin methods available within myModule by calling module.mixinMethod1() and have correct scope.
And referring to scope ... this is a closed address space created by functions.
Except for closures, scope only is available during a function's runtime
within this function's body. It never ever can be manipulated/spoofed.
The term one is looking for is context. JavaScript, being in many ways highly
dynamic, is build upon late binding (the object/target/context a method is called
on gets evaluated/looked up at runtime) and two kinds of delegation.
Context gets delegated either automatically by "walking the prototype chain"
or explicitly by one of both call methods which every function object does provide
- either call or apply.
Thus JavaScript already at language core level does offer a function based
Mixin pattern that is mightier than any of the available extend(s) or mixin
implementations for it provides delegation for free and is able of passing
around state which almost every of the blamed helpers does lack unless there
was effort of implementing this feature again in a rather roundabout fashion
(or ass-backwards to put it bluntly).
Bergi for his explanation already earned the bounties.
Within his answer's last paragraph there is a link to resources of mine that
already got outdated 3 month after giving the referred talk. Due of not having
enough reputation points, I'm not able to comment his answer directly. For this
I'll take the chance pointing now to the latest state of my personal research and
understanding of »The many talents of JavaScript for generalizing Role Oriented Programming approaches like Traits and Mixins«
Back again answering the OP's question.
I'm going to change the two first given code examples from the assumed module pattern
and the rather exemplarily provided mixin code base towards a plain constructor function
and what I'm meanwhile tempted to call a "proxified" and/or "bicontextual" mixin in order
to boil down the mechanics of delegating two different target/context objects at once.
Thus demonstrating a pure function based mixin pattern that might come closest to what
the OP tries to achieve.
var MyBicontextualMixin = function (localProxy) {
localProxy.proxifiedAccessible = function () {
console.log("proxified accessible.");
};
this.publiclyAccessible = function () {
console.log("publicly accessible.");
};
};
var MyConstructor = function () {
var localProxy = {};
MyBicontextualMixin.call(this, localProxy);
var locallyAccessible = localProxy.proxifiedAccessible;
// call 'em
locallyAccessible(); // "proxified accessible."
this.publiclyAccessible(); // "publicly accessible."
};
(new MyConstructor);
// will log:
//
// proxified accessible.
// publicly accessible.
This special pattern also is the underlying base for composing pure
function based Traits that rely on conflict resolution functionality
provided by "proxified" Mixins that won't expose this functionality
into public.
And for not ending up that theoretical there will be a "real world example",
composing a Queue module out of various reusable mixins that entirely
worship the approach of DRY. It also should answer the OP's question about
how to achieve encapsulation and exposition build only upon the module
pattern and function based mixin composition.
var Enumerable_first_last_item = (function (global) {
var
parseFloat = global.parseFloat,
math_floor = global.Math.floor,
// shared code.
first = function () {
return this[0];
},
last = function () {
return this[this.length - 1];
},
item = function (idx) {
return this[math_floor(parseFloat(idx, 10))];
}
;
return function () { // [Enumerable_first_last_item] Mixin.
var enumerable = this;
enumerable.first = first;
enumerable.last = last;
enumerable.item = item;
};
}(window || this));
var Enumerable_first_last_item_proxified = function (list) {
Enumerable_first_last_item.call(list);
// implementing the proxified / bicontextual [Enumerable_first_last_item] Mixin.
var enumerable = this;
enumerable.first = function () {
return list.first();
};
enumerable.last = function () {
return list.last();
};
enumerable.item = function (idx) {
return list.item(idx);
};
};
var Allocable = (function (Array) {
var
array_from = ((typeof Array.from == "function") && Array.from) || (function (array_prototype_slice) {
return function (listType) {
return array_prototype_slice.call(listType);
};
}(Array.prototype.slice))
;
return function (list) { // proxified / bicontextual [Allocable] Mixin.
var
allocable = this
;
allocable.valueOf = allocable.toArray = function () {
return array_from(list);
};
allocable.toString = function () {
return ("" + list);
};
allocable.size = function () {
return list.length;
};
Enumerable_first_last_item_proxified.call(allocable, list);
};
}(Array));
var Queue = (function () { // [Queue] Module.
var
onEnqueue = function (queue, type) {
//queue.dispatchEvent({type: "enqueue", item: type});
},
onDequeue = function (queue, type) {
//queue.dispatchEvent({type: "dequeue", item: type});
}/*,
onEmpty = function (queue) {
//queue.dispatchEvent({type: "empty"});
}*/,
onEmpty = function (queue) {
//queue.dispatchEvent("empty");
},
Queue = function () { // [Queue] Constructor.
var
queue = this,
list = []
;
queue.enqueue = function (type) {
list.push(type);
onEnqueue(queue, type);
return type;
};
queue.dequeue = function () {
var type = list.shift();
onDequeue(queue, type);
(list.length || onEmpty(queue));
return type;
};
//Observable.call(queue); // applying the [Observable] Mixin.
Allocable.call(queue, list); // applying the bicontextual [Allocable] Mixin.
},
isQueue = function (type) {
return !!(type && (type instanceof Queue));
},
createQueue = function () { // [Queue] Factory.
return (new Queue);
}
;
return { // [Queue] Module.
isQueue : isQueue,
create : createQueue
};
}());
var q = Queue.create();
//q.addEventListener("enqueue", function (evt) {/* ... */});
//q.addEventListener("dequeue", function (evt) {/* ... */});
//q.addEventListener("empty", function (evt) {/* ... */});
console.log("q : ", q); // { .., .., .., }
console.log("q.size() : ", q.size()); // 0
console.log("q.valueOf() : ", q.valueOf()); // []
"the quick brown fox jumped over the lazy dog".split(/\s+/).forEach(function (elm/*, idx, arr*/) {
console.log("q.enqueue(\"" + elm + "\")", q.enqueue(elm));
});
console.log("q.size() : ", q.size()); // 9
console.log("q.toArray() : ", q.toArray()); // [ .., .., .., ]
console.log("q.first() : ", q.first()); // "the"
console.log("q.last() : ", q.last()); // "dog"
console.log("q.item(2) : ", q.item(2)); // "brown"
console.log("q.item(5) : ", q.item(5)); // "over"
console.log("q.dequeue()", q.dequeue()); // "the"
console.log("q.dequeue()", q.dequeue()); // "quick"
console.log("q.dequeue()", q.dequeue()); // "brown"
console.log("q.dequeue()", q.dequeue()); // "fox"
console.log("q.dequeue()", q.dequeue()); // "jumped"
console.log("q.size() : ", q.size()); // 4
console.log("q.toArray() : ", q.toArray()); // [ .., .., .., ]
console.log("q.first() : ", q.first()); // "over"
console.log("q.last() : ", q.last()); // "dog"
console.log("q.item(2) : ", q.item(2)); // "lazy"
console.log("q.item(5) : ", q.item(5)); // undefined
.as-console-wrapper { max-height: 100%!important; top: 0; }
Related
Adding functions to the same namespace [duplicate]
How do I create a namespace in JavaScript so that my objects and functions aren't overwritten by other same-named objects and functions? I've used the following: if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();} Is there a more elegant or succinct way of doing this?
I use the approach found on the Enterprise jQuery site: Here is their example showing how to declare private & public properties and functions. Everything is done as a self-executing anonymous function. (function( skillet, $, undefined ) { //Private Property var isHot = true; //Public Property skillet.ingredient = "Bacon Strips"; //Public Method skillet.fry = function() { var oliveOil; addItem( "\t\n Butter \n\t" ); addItem( oliveOil ); console.log( "Frying " + skillet.ingredient ); }; //Private Method function addItem( item ) { if ( item !== undefined ) { console.log( "Adding " + $.trim(item) ); } } }( window.skillet = window.skillet || {}, jQuery )); So if you want to access one of the public members you would just go skillet.fry() or skillet.ingredients. What's really cool is that you can now extend the namespace using the exact same syntax. //Adding new Functionality to the skillet (function( skillet, $, undefined ) { //Private Property var amountOfGrease = "1 Cup"; //Public Method skillet.toString = function() { console.log( skillet.quantity + " " + skillet.ingredient + " & " + amountOfGrease + " of Grease" ); console.log( isHot ? "Hot" : "Cold" ); }; }( window.skillet = window.skillet || {}, jQuery )); The third undefined argument The third, undefined argument is the source of the variable of value undefined. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variable undefined is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable named undefined which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the value undefined.
I like this: var yourNamespace = { foo: function() { }, bar: function() { } }; ... yourNamespace.foo();
Another way to do it, which I consider it to be a little bit less restrictive than the object literal form, is this: var ns = new function() { var internalFunction = function() { }; this.publicFunction = function() { }; }; The above is pretty much like the module pattern and whether you like it or not, it allows you to expose all your functions as public, while avoiding the rigid structure of an object literal.
Is there a more elegant or succinct way of doing this? Yes. For example: var your_namespace = your_namespace || {}; then you can have var your_namespace = your_namespace || {}; your_namespace.Foo = {toAlert:'test'}; your_namespace.Bar = function(arg) { alert(arg); }; with(your_namespace) { Bar(Foo.toAlert); }
I normally build it in a closure: var MYNS = MYNS || {}; MYNS.subns = (function() { function privateMethod() { // Do private stuff, or build internal. return "Message"; } return { someProperty: 'prop value', publicMethod: function() { return privateMethod() + " stuff"; } }; })(); My style over the years has had a subtle change since writing this, and I now find myself writing the closure like this: var MYNS = MYNS || {}; MYNS.subns = (function() { var internalState = "Message"; var privateMethod = function() { // Do private stuff, or build internal. return internalState; }; var publicMethod = function() { return privateMethod() + " stuff"; }; return { someProperty: 'prop value', publicMethod: publicMethod }; })(); In this way I find the public API and implementation easier to understand. Think of the return statement as being a public interface to the implementation.
Because you may write different files of JavaScript and later combine or not combine them in an application, each needs to be able to recover or construct the namespace object without damaging the work of other files... One file might intend to use the namespace namespace.namespace1: namespace = window.namespace || {}; namespace.namespace1 = namespace.namespace1 || {}; namespace.namespace1.doSomeThing = function(){} Another file might want to use the namespace namespace.namespace2: namespace = window.namespace || {}; namespace.namespace2 = namespace.namespace2 || {}; namespace.namespace2.doSomeThing = function(){} These two files can live together or apart without colliding.
Here's how Stoyan Stefanov does it in his JavaScript Patterns book which I found to be very good (it also shows how he does comments that allows for auto-generated API documentation, and how to add a method to a custom object's prototype): /** * My JavaScript application * * #module myapp */ /** #namespace Namespace for MYAPP classes and functions. */ var MYAPP = MYAPP || {}; /** * A maths utility * #namespace MYAPP * #class math_stuff */ MYAPP.math_stuff = { /** * Sums two numbers * * #method sum * #param {Number} a First number * #param {Number} b Second number * #return {Number} Sum of the inputs */ sum: function (a, b) { return a + b; }, /** * Multiplies two numbers * * #method multi * #param {Number} a First number * #param {Number} b Second number * #return {Number} The inputs multiplied */ multi: function (a, b) { return a * b; } }; /** * Constructs Person objects * #class Person * #constructor * #namespace MYAPP * #param {String} First name * #param {String} Last name */ MYAPP.Person = function (first, last) { /** * First name of the Person * #property first_name * #type String */ this.first_name = first; /** * Last name of the Person * #property last_name * #type String */ this.last_name = last; }; /** * Return Person's full name * * #method getName * #return {String} First name + last name */ MYAPP.Person.prototype.getName = function () { return this.first_name + ' ' + this.last_name; };
I use this approach: var myNamespace = {} myNamespace._construct = function() { var staticVariable = "This is available to all functions created here" function MyClass() { // Depending on the class, we may build all the classes here this.publicMethod = function() { //Do stuff } } // Alternatively, we may use a prototype. MyClass.prototype.altPublicMethod = function() { //Do stuff } function privateStuff() { } function publicStuff() { // Code that may call other public and private functions } // List of things to place publically this.publicStuff = publicStuff this.MyClass = MyClass } myNamespace._construct() // The following may or may not be in another file myNamespace.subName = {} myNamespace.subName._construct = function() { // Build namespace } myNamespace.subName._construct() External code can then be: var myClass = new myNamespace.MyClass(); var myOtherClass = new myNamepace.subName.SomeOtherClass(); myNamespace.subName.publicOtherStuff(someParameter);
This is a follow-up to user106826's link to Namespace.js. It seems the project moved to GitHub. It is now smith/namespacedotjs. I have been using this simple JavaScript helper for my tiny project and so far it seems to be light yet versatile enough to handle namespacing and loading modules/classes. It would be great if it would allow me to import a package into a namespace of my choice, not just the global namespace... sigh, but that's besides the point. It allows you to declare the namespace then define objects/modules in that namespace: Namespace('my.awesome.package'); my.awesome.package.WildClass = {}; Another option is to declare the namespace and its contents at once: Namespace('my.awesome.package', { SuperDuperClass: { saveTheDay: function() { alert('You are welcome.'); } } }); For more usage examples, look at the example.js file in the source.
Sample: var namespace = {}; namespace.module1 = (function(){ var self = {}; self.initialized = false; self.init = function(){ setTimeout(self.onTimeout, 1000) }; self.onTimeout = function(){ alert('onTimeout') self.initialized = true; }; self.init(); /* If it needs to auto-initialize, */ /* You can also call 'namespace.module1.init();' from outside the module. */ return self; })() You can optionally declare a local variable, same, like self and assign local.onTimeout if you want it to be private.
The Module pattern was originally defined as a way to provide both private and public encapsulation for classes in conventional software engineering. When working with the Module pattern, we may find it useful to define a simple template that we use for getting started with it. Here's one that covers name-spacing, public and private variables. In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. What this results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page. var myNamespace = (function () { var myPrivateVar, myPrivateMethod; // A private counter variable myPrivateVar = 0; // A private function which logs any arguments myPrivateMethod = function( foo ) { console.log( foo ); }; return { // A public variable myPublicVar: "foo", // A public function utilizing privates myPublicFunction: function( bar ) { // Increment our private counter myPrivateVar++; // Call our private method using bar myPrivateMethod( bar ); } }; })(); Advantages why is the Module pattern a good choice? For starters, it's a lot cleaner for developers coming from an object-oriented background than the idea of true encapsulation, at least from a JavaScript perspective. Secondly, it supports private data - so, in the Module pattern, public parts of our code are able to touch the private parts, however the outside world is unable to touch the class's private parts. Disadvantages The disadvantages of the Module pattern are that as we access both public and private members differently, when we wish to change visibility, we actually have to make changes to each place the member was used. We also can't access private members in methods that are added to the object at a later point. That said, in many cases the Module pattern is still quite useful and when used correctly, certainly has the potential to improve the structure of our application. The Revealing Module Pattern Now that we're a little more familiar with the module pattern, let’s take a look at a slightly improved version - Christian Heilmann’s Revealing Module pattern. The Revealing Module pattern came about as Heilmann was frustrated with the fact that he had to repeat the name of the main object when we wanted to call one public method from another or access public variables.He also disliked the Module pattern’s requirement for having to switch to object literal notation for the things he wished to make public. The result of his efforts was an updated pattern where we would simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public. An example of how to use the Revealing Module pattern can be found below var myRevealingModule = (function () { var privateVar = "Ben Cherry", publicVar = "Hey there!"; function privateFunction() { console.log( "Name:" + privateVar ); } function publicSetName( strName ) { privateVar = strName; } function publicGetName() { privateFunction(); } // Reveal public pointers to // private functions and properties return { setName: publicSetName, greeting: publicVar, getName: publicGetName }; })(); myRevealingModule.setName( "Paul Kinlan" ); Advantages This pattern allows the syntax of our scripts to be more consistent. It also makes it more clear at the end of the module which of our functions and variables may be accessed publicly which eases readability. Disadvantages A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions. Public object members which refer to private variables are also subject to the no-patch rule notes above.
If you need the private scope: var yourNamespace = (function() { //Private property var publicScope = {}; //Private property var privateProperty = "aaa"; //Public property publicScope.publicProperty = "bbb"; //Public method publicScope.publicMethod = function() { this.privateMethod(); }; //Private method function privateMethod() { console.log(this.privateProperty); } //Return only the public parts return publicScope; }()); yourNamespace.publicMethod(); else if you won't ever use the private scope: var yourNamespace = {}; yourNamespace.publicMethod = function() { // Do something... }; yourNamespace.publicMethod2 = function() { // Do something... }; yourNamespace.publicMethod();
You can declare a simple function to provide namespaces. function namespace(namespace) { var object = this, tokens = namespace.split("."), token; while (tokens.length > 0) { token = tokens.shift(); if (typeof object[token] === "undefined") { object[token] = {}; } object = object[token]; } return object; } // Usage example namespace("foo.bar").baz = "I'm a value!";
I'm 7 years late to the party, but did quite a bit of work around this 8 years ago: http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html It is important to be able to easily and efficiently create multiple nested namespaces to keep a complex web application organized and manageable, while respecting the JavaScript global namespace (preventing namespace pollution), and with not clobbering any existing objects in the namespace path while doing so. From the above, this was my circa-2008 solution: var namespace = function(name, separator, container){ var ns = name.split(separator || '.'), o = container || window, i, len; for(i = 0, len = ns.length; i < len; i++){ o = o[ns[i]] = o[ns[i]] || {}; } return o; }; This isn't creating a namespace, but provides a function for creating namespaces. This can be condensed to a minified one-liner: var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g}; Example of use: namespace("com.example.namespace"); com.example.namespace.test = function(){ alert("In namespaced function."); }; Or, as one statement: namespace("com.example.namespace").test = function(){ alert("In namespaced function."); }; Either is then executed as: com.example.namespace.test(); If you don't need support for legacy browsers, an updated version: const namespace = function(name, separator, container){ var o = container || window; name.split(separator || '.').forEach(function(x){ o = o[x] = o[x] || {}; }); return o; }; Now, I'd be leery of exposing namespace to the global namespace itself. (Too bad the base language doesn't provide this for us!) So I'd typically use this myself in a closure, such as: (function(){ const namespace = function(name, separator, container){ var o = container || window; name.split(separator || '.').forEach(function(x){ o = o[x] = o[x] || {}; }); return o; }; const ns = namespace("com.ziesemer.myApp"); // Optional: ns.namespace = ns; // Further extend, work with ns from here... }()); console.log("\"com\":", com); In a larger application, this only needs to be defined once at the beginning of a page load (for client-based web apps). Additional files can then reuse the namespace function if kept (included as "optional" in the above). At worst, if this function is re-declared a few times - it's only a few lines of code, and less if minified.
I created namespace which is inspired by Erlang's modules. It is a very functional approach, but that is how I write my JavaScript code these days. It gives a closure a global namespace and exposes a defined set functions within that closure. (function(){ namespace("images", previous, next); // ^^ This creates or finds a root object, images, and binds the two functions to it. // It works even though those functions are not yet defined. function previous(){ ... } function next(){ ... } function find(){ ... } // A private function })();
After porting several of my libraries to different projects, and having to constantly be changing the top level (statically named) namespace, I've switched to using this small (open source) helper function for defining namespaces. global_namespace.Define('startpad.base', function(ns) { var Other = ns.Import('startpad.other'); .... }); Description of the benefits are at my blog post. You can grab the source code here. One of the benefits I really like is isolation between modules with respect to load order. You can refer to an external module BEFORE it is loaded. And the object reference you get will be filled in when the code is available.
I use the following syntax for the namespace. var MYNamespace = MYNamespace|| {}; MYNamespace.MyFirstClass = function (val) { this.value = val; this.getValue = function(){ return this.value; }; } var myFirstInstance = new MYNamespace.MyFirstClass(46); alert(myFirstInstance.getValue()); jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
I think you all use too much code for such a simple problem. No need to make a repo for that. Here's a single line function. namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window); Try it : // --- definition --- const namespace = name => name.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window); // --- Use ---- const c = namespace("a.b.c"); c.MyClass = class MyClass {}; // --- see ---- console.log("a : ", a);
ES6 Modules Namespace imports // circle.js export { name, draw, reportArea, reportPerimeter }; // main.js import * as Circle from './modules/circle.js'; // draw a circle let circle1 = Circle.draw(myCanvas.ctx, 75, 200, 100, 'green'); Circle.reportArea(circle1.radius, reportList); Circle.reportPerimeter(circle1.radius, reportList); This grabs all the exports available inside circle.js, and makes them available as members of an object Circle, effectively giving it its own namespace.
My favorite pattern has become lately this: var namespace = (function() { // expose to public return { a: internalA, c: internalC } // all private /** * Full JSDoc */ function internalA() { // ... } /** * Full JSDoc */ function internalB() { // ... } /** * Full JSDoc */ function internalC() { // ... } /** * Full JSDoc */ function internalD() { // ... } })(); Of course, return can be at the end, but if only function declarations follow it, it's much easier to see what's the namespace all about, and what API is exposed. The pattern of using function expressions in such cases results in not being able to know what methods are exposed without going over the entire code.
I like Jaco Pretorius' solution, but I wanted to make the "this" keyword a bit more useful by pointing it to the module/namespace object. My version of skillet: (function ($, undefined) { console.log(this); }).call(window.myNamespace = window.myNamespace || {}, jQuery);
JavaScript does not yet have a native representation of namespaces, but TypeScript does. For example, you could use the following TS code (playground) namespace Stack { export const hello = () => console.log('hi') } Stack.hello() If you can't update your code to TS, you can at least use the pattern employed by TS when generating the JS output for namespaces, which looks like this: var Stack; (function (Stack) { Stack.hello = () => console.log('hi'); })(Stack || (Stack = {})); Stack.hello(); Further Reading: TS - Namespaces TS - Namespaces and Modules
If using a Makefile you can do this. // prelude.hjs billy = new ( function moduleWrapper () { const exports = this; // postlude.hjs return exports; })(); // someinternalfile.js function bob () { console.log('hi'); } exports.bob = bob; // clientfile.js billy.bob(); I prefer to use a Makefile anyway once I get to about 1000 lines because I can effectively comment out large swaths of code by removing a single line in the makefile. It makes it easy to fiddle with stuff. Also, with this technique the namespace only appears once in the prelude so it's easy to change and you don't have to keep repeating it inside the library code. A shell script for live development in the browser when using a makefile: while (true); do make; sleep 1; done Add this as a make task 'go' and you can 'make go' to keep your build updated as you code.
Quite a follow-up of Ionuț G. Stan's answer, but showing the benefits of uncluttered code by using var ClassFirst = this.ClassFirst = function() {...}, which takes advantage of JavaScript's closure scoping for less namespace cluttering for classes in the same namespace. var Namespace = new function() { var ClassFirst = this.ClassFirst = function() { this.abc = 123; } var ClassSecond = this.ClassSecond = function() { console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc); console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc); } } var Namespace2 = new function() { var ClassFirst = this.ClassFirst = function() { this.abc = 666; } var ClassSecond = this.ClassSecond = function() { console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc); console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc); } } new Namespace.ClassSecond() new Namespace2.ClassSecond() Output: Cluttered way to access another class in namespace: 123 Nicer way to access a class in same namespace: 123 Cluttered way to access another class in namespace: 666 Nicer way to access a class in same namespace: 666
I've written another namespacing library that works a bit more like packages / units do in other languages. It allows you to create a package of JavaScript code and the reference that package from other code: File hello.js Package("hello", [], function() { function greeting() { alert("Hello World!"); } // Expose function greeting to other packages Export("greeting", greeting); }); File Example.js Package("example", ["hello"], function(greeting) { // Greeting is available here greeting(); // Alerts: "Hello World!" }); Only the second file needs to be included in the page. Its dependencies (file hello.js in this example) will automatically be loaded and the objects exported from those dependencies will be used to populate the arguments of the callback function. You can find the related project in Packages JS.
We can use it independently in this way: var A = A|| {}; A.B = {}; A.B = { itemOne: null, itemTwo: null, }; A.B.itemOne = function () { //.. } A.B.itemTwo = function () { //.. }
In JavaScript there are no predefined methods to use namespaces. In JavaScript we have to create our own methods to define NameSpaces. Here is a procedure we follow in Oodles technologies. Register a NameSpace Following is the function to register a name space //Register NameSpaces Function function registerNS(args){ var nameSpaceParts = args.split("."); var root = window; for(var i=0; i < nameSpaceParts.length; i++) { if(typeof root[nameSpaceParts[i]] == "undefined") root[nameSpaceParts[i]] = new Object(); root = root[nameSpaceParts[i]]; } } To register a Namespace just call the above function with the argument as name space separated by '.' (dot). For Example Let your application name is oodles. You can make a namespace by following method registerNS("oodles.HomeUtilities"); registerNS("oodles.GlobalUtilities"); var $OHU = oodles.HomeUtilities; var $OGU = oodles.GlobalUtilities; Basically it will create your NameSpaces structure like below in backend: var oodles = { "HomeUtilities": {}, "GlobalUtilities": {} }; In the above function you have register a namespace called "oodles.HomeUtilities" and "oodles.GlobalUtilities". To call these namespaces we make an variable i.e. var $OHU and var $OGU. These variables are nothing but an alias to Intializing the namespace. Now, Whenever you declare a function that belong to HomeUtilities you will declare it like following: $OHU.initialization = function(){ //Your Code Here }; Above is the function name initialization and it is put into an namespace $OHU. and to call this function anywhere in the script files. Just use following code. $OHU.initialization(); Similarly, with the another NameSpaces. Hope it helps.
My habit is to use function myName() as property storage, and then var myName as "method" holder... Whether this is legitimate enough or not, beat me! I am relying on my PHP logic all the time, and things simply work. :D function myObj() { this.prop1 = 1; this.prop2 = 2; this.prop3 = 'string'; } var myObj = ( (myObj instanceof Function !== false) ? Object.create({ $props: new myObj(), fName1: function() { /* code.. */ }, fName2: function() { /* code ...*/ } }) : console.log('Object creation failed!') ); if (this !== that) myObj.fName1(); else myObj.fName2(); You can also do it in a 'vice versa' way to check before object creation which is much better: function myObj() { this.prop1 = 1; this.prop2 = 2; this.prop3 = 'string'; } var myObj = ( (typeof(myObj) !== "function" || myObj instanceof Function === false) ? new Boolean() : Object.create({ $props: new myObj(), init: function () { return; }, fName1: function() { /* code.. */ }, fName2: function() { /* code ...*/ } }) ); if (myObj instanceof Boolean) { Object.freeze(myObj); console.log('myObj failed!'); debugger; } else myObj.init(); Reference to this: JavaScript: Creating Object with Object.create()
JavaScript doesn’t support namespace by default. So if you create any element(function, method, object, variable) then it becomes global and pollute the global namespace. Let's take an example of defining two functions without any namespace, function func1() { console.log("This is a first definition"); } function func1() { console.log("This is a second definition"); } func1(); // This is a second definition It always calls the second function definition. In this case, namespace will solve the name collision problem.
Writing JS Prototypes, should all functions use the Prototype object?
I'm beginning to learn more about writing JS using the Prototype object, but I want to make sure I don't pick up any bad habits from other developers. My understanding of using Prototype is to create public methods for your instance. For example: var module = new Module(); module.method(); But I see a lot of developers creating all their code inside the Prototype object, things that I would consider "private". Is this bad practice or considered okay? It just means I can then do: module.privateFn(); Do they know this? Is that okay? Any help appreciated. I've been looking through the source code on GitHub to try establish the best way forward, here's a script that uses Prototypes for everything (for instance attachEvent which they clearly want privately kept): https://github.com/WickyNilliams/headroom.js/blob/master/dist/headroom.js Much appreciated, I want to make sure I develop using the correct implementations.
First of all you don't need to write modules using prototype. Think like if you writing something like a class you should use prototypes. And also it's important to where define your methods. Defining methods on prototype object and defining them in constructor function is totally different things! Let's see a sample class definition with using methods defined in constructor: var Dog = (function () { var Dog = function (age, name) { var that = this; this.age = age; this.name = name; this.sayHi = function () { console.log('Warf! Im ' + that.name); // meaning of "this" changed!!! }; this.anotherMethod = function () {}; }; return Dog; }()); var puppy = new Dog(1, 'puppy'); // sayHi and anotherMethod created var sirius = new Dog(1, 'sirius'); // sayHi and anotherMethod recreated sirius.sayHi = function () { console.log('Yohalolop!'); }; puppy.sayHi(); // -> 'Warf! Im puppy' sirius.sayHi(); // -> 'Yohalolop!' So there is some problems with the above example, firstly methods are defined like any other instance variables. Actually yeah you define them as instance variable and this means this functions are recreated for every instance object you create. I guess you have mentioned you can't use this keyword in your method definitions. This is error prone and there is a chance to forget that and use this keyword by mistaken. There are some times you can use methods as instance variables of course like variable callbacks. Let's see a sample class definition with prototype object: var Dog = (function () { var Dog = function (age, name) { this.age = age; this.name = name; }; // sayHi method defined only once in prototype Dog.prototype.sayHi = function () { console.log('Warf! Im ' + this.name; // we can use this keyword }; // anotherMethod defined only once in protoype Dog.prototype.anotherMethod() { }; return Dog; }()); var puppy = new Dog(1, 'puppy'); var sirius = new Dog(1, 'sirius'); // sirius and puppy sharing same prototype object puppy.sayHi(); // -> 'Warf! Im puppy' sirius.sayHi(); // -> 'Warf! Im sirius' // remember puppy and sirius sharing same prototype object Dog.prototype.sayHi = function () { console.log('Yohalolop'); }; puppy.sayHi(); // -> 'Yohalolop' sirius.sayHi(); // -> 'Yohalolop' As an answer to your question about private functions, it is more complicated. Yes you can use private functions even you define your methods on prototype, but there are some concerns about testing. Usage of them is up to you. I prefer to don't use. Let me show some examples. var Calculator = (function () { var Calculator = function () { this.importantNumber = 2; }; // There is unfortunately no native implementation // for private methods but you can mimic them with // unaccessible functions and binding. var someExtremeComputations = function () { return 40 + this.importantNumber; // this keyword points to instance because of binding }; Calculator.prototype.getMeaningOfLife = function () { var result = someExtremeComputations.call(this); // we bind function to instance return result; }; return Calculator; }()); This is the one of the examples how you can define private methods in javascript. The problem with private functions, they can't be tested. There is no way to test someExtremeComputations method. Some people (includes me) use prefixed underscore naming convention for private methods. So they are actually public methods but if someone calling them or overriding they were warned by prefixed underscore. After all we can test private methods since they are public in real. var Calculator = (function () { var Calculator = function () { this.importantNumber = 2; }; // private method's name prefixed by an underscore to warn // other developers to be careful about that or not to use. Calculator.prototype._someExtremeComputations = function () { return 40 + this.importantNumber; }; Calculator.prototype.getMeaningOfLife = function () { var result = this.someExtremeComputations(); // no need to bind return result; }; return Calculator; }());
Explaining this with a few words is impossible. A generally good pattern is to construct methods through prototypes when you want to optimize your code. A good guideline is to only put the most essential data in the memory, using prototypes is critical for this since the prototyped variables and methods isn't injected into the memory until you request them. When it comes yo your example there are no prototypes. Simple example // new object var Dog = function() { var that = this; // add a property that.name = "Fido"; // add a method that.getName = function() { return that.name; }; }; // ... all the above is stored in memory directly // Requires to be constructed var dogObj = new Dog(); console.log(dogObj.getName()); // Fido delete Dog.name // false typeof Dog.name // "string" delete dogObj.name // true typeof dogObj.name // "undefined" typeof Dog.name // "string" (still there) // Will be available in the dogObj (after you call it) dog.prototype.first = "first"; // Will be available in the dogObj (after you call it) dog.prototype.second = function() { return "second"; } // Will not be available in dogObj dog.third = "third";
Difference between javascript constructors
I'm having a bit of confusion over which (if any) of these javascript initializes to use, as from what I can tel, they all do the same thing. Are there cases in which I should use one or he other? Mt project requires me to encapsulate several functions and namespaces in a single object so that we don't clutter te global scope with variable names, put I'm especially unclear as to the difference between +function(){}(); and (function())(); Any help would be greatly appreciated. Keep in mind the end goal is for all of our function to be encapsulated in a single namespace. IE MyCompany.function, MyCompany.Namepsace.Function ... <script> var Ford = {}; +function() { Ford.start = function() { console.log("Ford just started"); }; }(); Ford.start(); </script> <script> var Honda = {}; (function() { Honda.start = function() { console.log("Honda just srtarted"); }; })(); Honda.start(); </script> <script> var Toyota = function() { return { start: function() { console.log("Toyota just strted"); } }; } var car = new Toyota(); car.start(); </script>
Javascript functions are only invoked as constructors when the new keyword is used. new creates a new object instance, inherits from the constructor's prototype, and makes the context of the this keyword the newly created object instance. So if you're not using the prototype to inherit properties or the keyword this to create new properties in the constructor--you don't really need to use a constructor. I think what you're looking for is the module pattern which is implemented using immediately invoked functions. Both of your first two examples use immediately invoked functions. I believe the style (function(){}()); is preferred to +function(){}();. Both the surrounding () and the + cause the javascript parser to expect a function expression rather than a function declaration and this allows the trailing () to invoke the function. Besides being somewhat less readable + may also alter the return value of the function. I think you want some variation on this (copied from link): var MODULE = (function () { var module = {}; var privateVariable = 1; function privateMethod() { // ... } module.moduleProperty = 1; module.moduleMethod = function () { // ... }; return module; }());
While all of that is valid JS, you're making assumptions that lead me to believe you may not understand how JS works. The first two example are not constructors in the usual sense at all...they're sort of module pattern, but not even. you could condense it to var Honda = {}; Honda.start = function() { console.log("Honda just started"); } and forget the self-executing function. What is shown above is similar to what you'd think of as a static function in other languages: public class Honda { public static void start() { Console.WriteLine("Honda Just Started"); } } If you wanted an instance function, you need to either attach to the prototype, or to the this keyword in the constructor: Prototype: var Honda = function() {} Honda.prototype.start = function() { console.log("Honda just started"); } This: var Honda = function() { this.start = function(){ console.log("Honda just started"); } } Your final example, with Toyota indicates you have a fundamental misunderstanding of how function constructors work. Your object has been discarded, and in return you get some object literal which could have been written: var Toyota = { start: function(){ console.log("Toyota just started"); } } What you (probably) intend is the "this" pattern I explained on the Honda example above: var Toyota = function() { this.start = function() { console.log("Toyota just started"); } } Finally, when writing "namespaced" libraries of functions, the module pattern may be your best friend. This lets you maintain private state without the need for a formal constructor/prototypes, etc: var MyCompany = {}; //car module (function(ns){ var module, _isStarted; function start() { console.log('start'); _isStarted = true; } function stop() { console.log('stop'); _isStarted = false; } function isStarted() { return _isStarted; } module = { start: start, stop: stop, isStarted: isStarted } ns.CarModule = module; }(MyCompany)); //use: MyCompany.CarModule.start(); if(MyCompany.CarModule.isStarted()) { MyCompany.CarModule.stop(); }
Javascript Sandbox Pattern example implementation
On Page 101 of Stoyan Stefanov's great book "JavaScript Patterns" he explains the sandbox pattern. I liked his book much but I really missed some real life examples here and then to better understand what he talks about. Like the sandbox pattern! I'm looking for a real life working implementation, like a copy&paste starting point, just a simple example that will work to fully understand it. Is there any?
I've simplified Stoyan's example in an attempt to make it easier to understand what's going on. I've also commented it more thoroughly. /*First define the modules of the sandbox. These will be defined as properties on the constructor function because this is a convenient place to keep them.*/ Sandbox.modules = {}; Sandbox.modules.returnNumbers = function(MYAPP) { MYAPP.return100 = function() {return 100;}; }; Sandbox.modules.returnLetters = function(MYAPP) { MYAPP.returnABC = function() {return "ABC";}; }; function Sandbox() { /* Because Sandbox is a constructor, an new object is automatically created. Because we're in the constructor, we refer to this new object as 'this'. A constructor would typically be used as part of an assignment, e.g. myObject = new Sandbox(). However, it's also legitimate javascript to use a constructor without the assignment by just writing new Sandbox() with no assignment. The constructor does return an object, it's just that it doesn't get assigned to anything so is discarded. We're going to add functionality (methods) to the 'this' object, but rather than returning it, we will pass it to the callback function, so the methods can be used immediately. */ var args = Array.prototype.slice.call(arguments); //Put the arguments //of the call to the Sandbox constructor in an array called args. var callback = args.pop(); //The last argument is the callback var requiredmodules = args; //The remaining arguments are the require // modules //For each of the modules in 'requiredmodules', add the module's //methods to 'this' for (i=0; i< requiredmodules.length; i++) { Sandbox.modules[requiredmodules[i]](this); } //'this' now has methods returnNumbers and returnLetters //Call the callback. In the example below, 'this' will be called //MYAPP, which within the callback will have all the methods from //the required modules. callback(this); } //Finally here is an example of usage new Sandbox('returnNumbers', 'returnLetters', function (MYAPP) { console.log(MYAPP.return100()); console.log(MYAPP.returnABC()); });
Stoyan Stefanov mentions in the same chapter that YUI version 3 implements the Sandbox pattern. The YUI add method (API) registers modules and the use method (API) loads the specified ones in the sandbox instance. There are links to the source js file in the API documentation. Virtually all YUI code examples use this pattern to work with the YUI library. Defining a module is rarely needed - YUI has many core ones and there is a page for custom modules added by the community.
So I tried and came up with this solution: function Sandbox() { // turning arguments into an array var args = Array.prototype.slice.call(arguments), // the last argument is the callback callback = args.pop(), // modules can be passed as an array or as individual parameters modules = (args[0] && "string" === typeof args[0]) ? args : args[0], i; // make sure the function is called // as a constructor if (!(this instanceof Sandbox)) { return new Sandbox(modules, callback); } // add properties to 'this' as needed: this.a = 1; this.b = 2; // now add modules to the core 'this' object // no modules or "*" both mean "use all modules" if (!modules || '*' === modules) { modules = []; for (i in Sandbox.modules) { if (Sandbox.modules.hasOwnProperty(i)) { modules.push(i); } } } // initialize the required modules for (i = 0; i < modules.length; i += 1) { Sandbox.modules[modules[i]](this); } // call the callback callback(this); // any prototype properties as needed Sandbox.prototype = { name: "Sandbox", version: "1.0", getName: function() { return this.name; } } }; Sandbox.modules = {}; Sandbox.modules.color = function (box) { // private var initialColor = $('#main').css('color'); // set a red color box.setMainRed = function() { $('#main').css('color','red'); return false; }, // get the current color box.getInitialColor = function () { return initialColor; }; } // another module Sandbox.modules.style = function (box) { // set a red color box.setStyle = function() { $('#main').css('font-style','italic'); return false; }; } // page ready $.ready( Sandbox(['color', 'style'], function (box) { console.log(box); box.setMainRed(); box.setStyle(); console.log('try access initialColor: ', box.initialColor); console.log('get initial color: ', box.getInitialColor()); }) ); But I am really unsure weather this is what I should be doing. Especially adding the "modules" is somewhat confusing. Also earlier in the book he uses the namespace-pattern for this task, but not here. Why? Can't you do it here too? But I failed to combine these two patterns. Namespace pattern example inspired by the book: var APP = APP || {}; // namespace function APP.namespace = function (nsString) { var parts = nsString.split('.'), parent = APP, i; // strip redundant leading global if ("APP" === parts[0]) { parts = parts.slice(1); } for (i = 0; i < parts.length; i += 1) { // create a property if it doesn't exist if ("undefined" === typeof parent[parts[i]]) { parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; } // constructors APP.namespace('modules.Color'); // immediate function APP.modules.Color = (function () { var currentColor = $('#main').css('color'), // set a red color setMainRed = function() { $('#main').css('color','red'); return false; }, // get the current color getCurrentColor = function () { return currentColor; }; // revealing module pattern return { setMainRed: setMainRed, getCurrentColor: getCurrentColor }; }()); var doSomething = function () { var color = APP.modules.Color; color.setMainRed(); console.log(color.currentColor); console.log(color.getCurrentColor()); return false; } // page ready $.ready( doSomething() );
Here is example with detailed comments: (function(){ /* function constructor */ function Sandbox(){ //Change arguments to array, as you know 'arguments' are not a true JS array //Array.prototype.slice will provide shallow copy of 'arguments' var args = Array.prototype.slice.call(arguments), //remove last element from array and return it to caller //our last argument is callback callback = args.pop(), //We can pass modules as strings or as array //if first element is a string, take all arguemnts //otherwise take one element (array) modules = (args[0] && typeof args[0] === "string") ? args : args[0], modulesLength = modules.length, i; //handle calling function constructor without 'new' keyword if(!(this instanceof Sandbox)){ //Invoke me again! return new Sandbox(modules, callback); } //we can add properties to 'this' this.someProp = "Initialized property"; //Initialize all required modules for(i = 0; i < modulesLength ; i++){ //pass reference to 'this' for each required module and invoke it //'this' is poiting to new object which was created //after calling new Sandbox() Sandbox.modules[modules[i]](this); } //Invoke callback and pass 'this' //now 'this' cotains all methods and properties //attached in modules functions callback(this); }; //We can optionally create Sandbox methods Sandbox.prototype = { version: "1.0.1", createdAt: new Date() }; /* function as a first class object - saving all modules*/ Sandbox.modules = {}; /*Create $http,$scope and $ajax modules */ /*We need box object to add new functionality*/ /*We are creating new methods by attatching them to box obect*/ /*box is a reference to 'this' called as initializator from function constructor*/ Sandbox.modules.$http = function(box){ box.get = function(){ console.log("$http.get"); }; box.post = function(){ console.log("$http.post"); }; box.prop = "I'm $http property"; }; Sandbox.modules.$scope = function(box){ box.inject = function(param1, param2){ console.log("$scope.inject: " + param1 + " " + param2); }; box.destroy = function(o){ console.log("$scope.destroy: " + o + " has been destroyed!"); }; }; Sandbox.modules.$ajax = function(box){ box.call = function(){ console.log("$ajax.call"); }; }; //Sandbox without calling 'new' was handled in function constructor //We are requesting for 2 modules: $scope and $http //callback function is our new playground //box object has $scope and $http methods and properties inside, we are ready to go! Sandbox(["$scope", '$http'], function(box){ console.log(box); //contains methods from $scope and $http console.log(box.inject("John", "Doe")); console.log(box.post()); //we can event nest our playgrounds Sandbox(["$ajax"], function(box){ console.log(box); //contains only $ajax methods and properties console.log(box.call()); //we can't invoke $scope or $http functions here }); //we can't invoke $ajax functions here }); })(); Link to JSFiddle: http://jsfiddle.net/Lodse4hj/
Encapsulation in javascript
I need to create simple reusable javascript object publishing several methods and parameterized constructor. After reading through several "OOP in JavaScript" guides I'm sitting here with an empty head. How on the Earth can I do this? Here my last non-working code: SomeClass = function(id) { this._id = id; } (function() { function intFun() { return this._id; } SomeClass.prototype.extFun = function() { return incFun(); } })();
This is my usual approach: MyClass = function(x, y, z) { // This is the constructor. When you use it with "new MyClass()," // then "this" refers to the new object being constructed. So you can // assign member variables to it. this.x = x; ... }; MyClass.prototype = { doSomething: function() { // Here we can use the member variable that // we created in the constructor. return this.x; }, somethingElse: function(a) { } }; var myObj = new MyClass(1,2,3); alert(myObj.doSomething()); // this will return the object's "x" member alert(myObj.x); // this will do the same, by accessing the member directly Normally the "this" keyword, when used in one of the object's methods, will refer to the object itself. When you use it in the constructor, it will refer to the new object that's being created. So in the above example, both alert statements will display "1". An exception to this rule is when you pass one of your member functions somewhere else, and then call it. For example, myDiv.onclick = myObj.doSomething; In this case, JavaScript ignores the fact that "doSomething" belongs to "myObj". As a result, the "this" inside doSomething will point to another object, so the method won't work as expected. To get around this, you need to specify the object to which "this" should refer. You can do so with JavaScript's "call" function: myDiv.onclick = function() { myObj.doSomething.call(myObj); } It's weird, but you'll get used to it eventually. The bottom line is that, when passing around methods, you also need to pass around the object that they should be called on.
I usually don't worry too much about hiding the internals, although I do prefix them with underscores to mark them as not intended to be used outside the "class". Normally what I will do is: var MyClass = function() {}; MyClass.prototype = { _someVar : null, _otherVar : null, initialize: function( optionHash ) { _someVar = optionsHash["varValue"]; _otherVar = optionsHash["otherValue"]; }, method: function( arg ) { return _someVar + arg; }, }; And use it as so... var myClass = new MyClass( { varValue: -1, otherValue: 10 } ); var foo = myClass.method(6);
All vars are private: SomeClass = function (id) { var THIS = this; // unambiguous reference THIS._id = id; var intFun = function () { // private return THIS._id; } this.extFun = function () { // public return intFun(); } } Use THIS within private methods since this won't equal what you might expect.
From http://learn.jquery.com/code-organization/concepts/#the-module-pattern: // The module pattern var feature = (function() { // private variables and functions var privateThing = "secret"; var publicThing = "not secret"; var changePrivateThing = function() { privateThing = "super secret"; }; var sayPrivateThing = function() { console.log( privateThing ); changePrivateThing(); }; // public API return { publicThing: publicThing, sayPrivateThing: sayPrivateThing }; })(); feature.publicThing; // "not secret" // logs "secret" and changes the value of privateThing feature.sayPrivateThing(); So using returning an object that aliases its "methods" could be another way to do it. I've read from http://www.amazon.com/Programming-Oracle-Press-Poornachandra-Sarang-ebook/dp/B0079GI6CW that it is always good practice to use getters and setters rather that accessing the variable directly from outside the object, so that would eliminate the need of returning variables by reference. BTW you could just use this.variable to reference/declare a public variable and var variable to declare a private variable. I know this is a late answer, but I hope it helps anyone who reads it in the future.