Return structure on JS Module Pattern - javascript

Building a best practices for a manual on Module Patterns (for an internal's firm course) We come to the needs of easy discussion on the public contract and the persistence of each object. So the team is divided between two structures:
CLASSIC:
// Namespace for the library
var myFunPattern1 = {};
// Library definition
myFunPattern1 = (function () {
// Private variables / properties
var myPrivateVar = "anyValue"
// Private methods
function anyPrivateMethod(parameter) {
...
return "whatever";
}
// Public API
return {
anyPublicMethod: function (parameter) {
...
return "whatever";
}
};
})();
THE OTHER:
// Namespace for the library
var myFunPattern2 = {};
// Library definition
myFunPattern2 = (function () {
// Public API
return {
anyPublicMethod: internalNameForPublicMethod
};
// Private variables / properties
var myPrivateVar = "anyValue"
// Public methods
function internalNameForPublicMethod(parameter) {
...
return "whatever";
}
// Private methods
function anyPrivateMethod(parameter) {
...
return "whatever";
}
})();
we see the first of more "code elegant" while the second enables faster development and clear conversation between teams (once the return is defined with the documentation for parameters and so on, each developer can start working on the rest of the code
also, changes on the functionality (i.e A/B testing on function performance), on first mode need to be changed the function, on second, only the internal reference. Even, that may could be done dynamically ...
some of us think the second may raise some inconsistencies and force dependencies (public functions being declared first, or invoque before declaration), others we think we are safe ...
any other consideration??

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";

Javascript mixins when using the module pattern

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; }

Why do we need private variables?

What are they for and how do we make it? Can you give me an example?
To avoid collisions with multiple libraries, for example.
Say they both use a variable commonly used such as data. If both libraries use private variables it's all fine:
var lib1 = (function() {
var data;
return {
get: function() { return data },
set: function(v) { data = v }
};
})();
// Supposed to do something different:
var lib2 = (function() {
var data;
return {
get: function() { return data },
set: function(v) { data = v }
};
})();
lib1.set(123);
lib2.set(456);
lib1.get(); // 123
lib2.get(); // 456
However suppose they don't use private variables but global ones like this:
var lib1 = (function() {
return {
get: function() { return data },
set: function(v) { data = v }
};
})();
// Supposed to do something different:
var lib2 = (function() {
return {
get: function() { return data },
set: function(v) { data = v }
};
})();
lib1.set(123);
lib2.set(456);
lib1.get(); // 456 - overwritten by lib2. lib1 might not work properly anymore.
lib2.get(); // 456
So lib1.get() will fetch the same data as lib2.get().
This example is too obvious of course but to stay safe it's a good practice to use private variables.
Variables are encapsulated within a class to stop their names colliding. These can be public or private. Sometimes there is a need to make sure that variables are only changed using the functions that set them. For example the parts of a date would need to be verified to stop someone setting an invalid date such aas February 45th.
var factorial = (function(){
var precog = [1,1];// ===undefined for other indices, N = undefined || N
return function(y){
return precog[y] || (precog[y]=y*arguments.callee(y-1));
};
})();
Here is a JavaScript function with a private precog. This stores previously calculated values and it is private to stop them being manipulated.
I believe there are multiple reasons for namespaces. One way I understand it is: private, protected, and public expressions help a lot in team environments so that other devs don't end up using methods you didn't intend them to. That being said, you only use private when methods or properties only need to be accessed by that same object. Use protected when you need an inheriting class to carry that same functionality and use public when an object of a different class needs to access your object.
eg:
Class Victim has
private method haveAnxiety()
public property appearsToBeRich:Boolean
Class Robber has
private method profile(obj:Victim)
private method rob(obj:Victim)
Robber->profile() will need to access Victim->appearsToBeRich. If Victim->appearsToBeRich returns true, then that Victim object will get robbed. a Robber object never needs to run Victim->haveAnxiety as the Victim will run this->haveAnxiety() as soon as that Victim object starts getting robbed.
Granted, real world examples are a LOT more complex than my example (and I hope they are much more graceful). Anyway, I hope that helps.

Creating new JS library - Help deciding the base structure

Im creating a new library for a company. The structure I follow is
(function() {
var lib = function() {
//some private and public fn definitions
//setting publically avbl functions
return {
func1 : func1, func2: func2
};
};
return (window.lib = lib);
})();
Now how I call this is
lib.func1();
I want to be able to call my library as
lib(function | string | object).someproperty
How do I convert my code. Tried something like this
function lib() {
return new arguments.callee(arguments);
}
lib.prototype={
publicfunc: function() {
}
}
In this i'm having some problems accessing private functions since it is out of the scope for the public functions defined in the lib's prototype.
var lib = (function (param) {
var func = function () {
/// your code
return {
animate : function () {
// do the animation
return this;
}
}
return func;
})();
this can be the basic fprmat.
ok here is how i can be used.
lib(function() {...});
or
lib(selectItem).animate();
because i returned this i can run another method if there is any.
lib(selectItem).animate().animate().animate().animate() ....;
i hope you can find a use of this format, of course i made it very basic
In this i'm having some problems accessing private functions since it is out of the scope for the public functions defined in the lib's prototype.
This is because there is no such thing as private there is only local. You cannot access local variables out of scope.
The prototype cannot talk to local variables in the constructor. There are various hacks around this like keeping a public hash of instances but then you lose the "privacy"

Categories

Resources