This is a js pattern I've found myself using and tweaking over the years.
The thing is, I fell into it after some experimentation and I'm keen to know whether this type of pattern has a name. I've browsed through a lot of design patterns but not found anything similar (or as simple, especially for modular type patterns).
var FOO = (function ($) {
var privateFuncA = function() {
...
},
privateFuncB = function() {
...
},
self = {
init: function() {
privateFuncA(); // Call a private func
self.publicFunc(); // Call a public func
},
publicFunc: function() {
...
}
};
return self;
}(jQuery));
$(function () {
// Initialise FOO
FOO.init();
});
Idea is to keep everything namespaced and allows for pseudo-public/private funcs.
If I need to go modular I'll extend the base FOO object:
// Extend FOO object
FOO.Bar = (function ($) {
var privateFunc = function() {
...
},
self = {
publicFunc: function() {
...
}
};
return self;
}(jQuery));
If you want to call publicFunc in the extended object from outside you can:
FOO.Bar.publicFunc()
Does anyone know if this type of pattern has a name or whether there's any known issues with such a design?
Sure. It's just an extension of Christian Hielmann's "Revealing Module" pattern, which was itself an extension of Douglas Crockford's Module pattern.
In a lot of my examples here on SO, I'll use something very similar, except replacing self with public_interface, to try to make it more obvious as to what is public, private or private-static.
var built_module = (function () {
var private_data = "",
private_method = function () { /* ... */ },
public_interface = {
public_method : function () { /* ... */ },
public_data
};
return public_interface;
}());
and as a constructor:
var built_constructor = (function (env_params) {
var static_data = "",
static_method = function () { /* ... */ },
public_constructor = function (params) {
var private_data = "",
private_method = function (params) { /* ... */ },
public_interface = {
public_method : function () { /* ... */ },
public_data
};
return public_interface;
};
return public_constructor;
}(envArgs));
var myInstance = built_constructor(myArgs);
The "static" data/properties are in an outer-closure, so all of the vars/functions within the inner-closure have access to them, while the "static" methods have no access to any instance-methods/data, without passing arguments into the function.
You can extend it in any way from here -- removing the return value, and instead assigning the public_interface as a property of an object, or window by default (for namespacing).
Related
I want to store a function, internal to the function-object its within, in an object member, but I need to get access to it via name. The code below makes it easier to understand...
// MyClassThing.js:
var MyClassThing = (function() {
var _ref = {obj: undefined, fnc: undefined};
function setup(domObject, refName) {
_ref.obj = domObject;
_ref.fnc = this['func_' + refName]; // <<-- This does not work!!
}
function doThing() {
if(_ref.func)
_ref.fnc();
}
function func_foo() {
console.log('Foo!');
}
return {
setup: setup,
doThing: doThing
};
})();
// index.html
<script>
MyClassThing.setup($('#fooObj'), 'foo');
MyClassThing.doThing();
</script>
What do I do to get _ref.fnc = ???? to work properly?
You will have to use helper object to put methods as its properties. Then you will be able to refer to them by variable name:
var MyClassThing = (function () {
var _ref = { obj: undefined, fnc: undefined },
methods = {};
function setup(domObject, refName) {
_ref.obj = domObject;
_ref.fnc = methods['func_' + refName];
}
function doThing () {
if (_ref.fnc) _ref.fnc();
}
methods.func_foo = function () {
console.log('Foo!');
};
return {
setup: setup,
doThing: doThing
};
})();
You can't use this because it points to the object returned from IIFE, however your methods of interest are not properties of this object.
There's a typo in your code:
var MyClassThing = (function() {
var _ref = {obj: undefined, fnc: undefined};
function setup(domObject, refName) {
_ref.obj = domObject;
_ref.fnc = this['func_' + refName]; // <<-- This does not work!!
}
function doThing() {
if(_ref.fnc)
_ref.fnc();
}
function func_foo() {
console.log('Foo!');
}
return {
setup: setup,
doThing: doThing
};
})();
In your doThing function, you are checking for the existency of a _ref.func instead of _ref.fnc
To achieve what you want to do, you need to understand that the functions you are declaring using the "function" are not linked to the class. There's no notion of "private member function" in javascript. If you want to bind a function to a class, you need to declare it like this (there are other ways, i'm just showing you one of them) :
MyClassThing.prototype.func_foo = function () {
}
The best thing to do, in your case, would be to set _ref.fnc to func_foo directly. If you want to keep the this context, take a look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
I have my javascript code as follow:
$(document).ready(function () {
//call of global functions
globalFunction1();
globalFunction2(); //create a new object inside
globalFunction3();
}
function globalFunction1() {
// do something directly with jquery selectors
var testObj1 = new object1($('#tree')); // this is called later in the function
testObj.doSomething();
}
function globalFunction2() {
// do other things
}
function globalFunction3() {
// do something directly with jquery selectors
}
//creating an object in js
var object1 = (function () {
var tree;
function object1($tree) {
tree = $tree;
});
}
object1.prototype.doSomething = function () {
.....
};
return fancyStructure;
})();
Normally I have more global functions and if possible I always try to create objects using the new keyword (as in Java or C#)
Now, I am asked to provide namespacing in order to avoid function conflict problems. Thing is I am not sure how to achieve that giving my current code and knowing that I need to keep the code Object Oriented.
Hence, I am wondering if there is a way to add some namespacing effisciently. Any suggestion will do as long as it is along the lines of adding a namespace.
Just put your functions into an Object:
var mynamespace = {
globalFunction1 : function() {
// do something directly with jquery selectors
var testObj1 = new object1($('#tree')); // this is called later in the function
testObj.doSomething();
},
globalFunction2 : function() {
// do other things
},
globalFunction3 : function() {
// do something directly with jquery selectors
}
}
and call the functions with
mynamespace.globalFunction1();
Or you could just define your namespace
mynamespace = {};
And later add the the functions with
mynamespace.globalFunction1 = function() {
//do something
};
Use objects as containers for your functions. This is the standard approach of code structuring in JS.
var namespace1 = {
func1: function() {},
func2: function() {},
}
var namespace2 = {
func1: function() {},
func2: function() {},
}
namespace1.func2();
You can store your OOP code in this namespaces:
var namespace3 = {
someObj: function() {},
create: function() { return new this.someObj(); },
}
namespace3.someObj.prototype = {
count: 15,
someFunc() {}
}
And you can easily extend them:
namespace3.anotherObj = function () {}
Edit
Regarding your example:
var fancyStructureWrapped = (function () {
var tree;
function fancyStructure($tree) {
tree = $tree;
});
fancyStructure.prototype.doSomething = function () {
.....
};
return fancyStructure;
})();
// add it to some namespace
someNamespace.fancyStructure = fancyStructureWrapped;
//create an instance
var fs = new someNamespace.fancyStructure();
//and use it
fs.doSomething();
If you're looking for a general approach to managing a growing JavaScript codebase, check out RequireJS and/or Browserify. Both are libraries that allow dividing your code up into modular bits (ie. AMD or CommonJS modules) and then referencing/importing between them. They include tooling for bundling these files into a single JS file when it's time to deploy a production build too.
I've searched on SO and elsewhere for a simple example of inheritance and can't find one. Examples I've seen are obscure, complex, or just make me uncomfortable. I have several service functions that all share some functionality, from what I would call a baseservice:
function baseservice() {
var loadAnimate = function () {
$('#ajax-spinner').show();
};
var loadComplete = function () {
$('#ajax-spinner').hide();
};
var apiEndpoint = function() {
return "http://api.com/api/";
};
};
I have other services now that have this functionality:
var documentservice = function() {
// repeated code
var loadAnimate = function () {
$('#ajax-spinner').show();
};
var loadComplete = function () {
$('#ajax-spinner').hide();
};
var apiEndpoint = "http://api.com/api/";
var sendRequest = function (payload, callback) {
loadAnimate();
// do stuff with apiEndpoint
// call loadComplete on promise
};
How can I provide documentservice with access to those items in baseservice?
Since Javascript is a prototypical language, it doesn't have the same sort of class inheritance that a language like, say, Java has. If you want a very simple instance of inheritance, you could try something like:
function baseservice() {
this.loadAnimate = function () {
$('#ajax-spinner').show();
};
this.loadComplete = function () {
$('#ajax-spinner').hide();
};
this.apiEndpoint = function() {
return "http://api.com/api/";
};
};
var documentservice = new baseservice();
documentservice.sendRequest() = function() { /* ... */ }
Then, documentservice has all of baseservice's members (note the this. in baseservice's function declaration instead of var).
If you don't want to have to use the new keyword, you can create a function extend either adds a field pointing to baseservice (document.baseservice = baseservice) or does a deep (recursive) copy, then adds documentservice.sendRequest.
Of course, folks have already worked on this with things like ded/klass.
Is it possible to have private properties in a model? Like the locally declared variables in a (constructor) function, not attached to this, but declared locally and visible only by whatever is defined in the (constructor)function.
Example without BB View:
function MyView(aModel){
var $internalInput = $('<input>');
this.render: function($where){
$internalInput.val(aModel.get('SomeProperty'));
$where.append($('<div class="inputWraper">').append($internalInput));
};
this.toggleReadonly: function() {
toggle $internalInputs readonly attribute
}
...
+ Code to bind input.val to some aModel property(ies) and setup events
...
}
Note that internalInput is not accessible to outside world and aModel is also not accessible (through MyView at least).
So if I want to use Backbone.View to implement the above MyView, how would i do it and keep $internalInput 'private'?
You should be able to achieve private data by passing an IIFE to extend when defining your Backbone objects, rather than just a plain object. For example:
var Thing = Backbone.Model.extend((function () {
var foo = "Private data!";
return {
bar: function () {
console.log(foo);
}
};
})());
You'd better off with
var Thing = Backbone.Model.extend(
{
constructor : function ()
{
var _value = "Private data!";
this.getValue = function ()
{
return _value;
};
this.setValue = function (value)
{
_value = value;
};
}
});
Javascript is fun!
var Thing = (function () {
var number_of_things = 0;
return function (options) {
var value = "Private data!";
return new ( Backbone.Model.extend({
constructor: function constructor () {
number_of_things += 1;
},
getValue: function getValue () {
return value;
}
}) )();
};
}());
I'm a little concerned by the fact that every instance of this "Thing" is also a subclass, in the OOP lingo.
In the context of using Broserify.js with Backbone (and really any above medium project) I found the following way to have private vars and functions:
myView.js
'use strict';
var config = require('../config.js'),
private_var = 'private variable',
my_private_fn = function() {
...
};
module.exports = Backbone.Model.extend({
initialize: function() {
this.my_public = 'public variable');
console.log('This is my' + this.my_public);
console.log('This is my' + my_private);
},
});
The idea to take here is go with Browserify :P
The simplest way is the following:
...
initialize:function(properites){
// Init the logic with private and public methods/variable
this.logic.initFirst(this);
// Use public methods
this.logic.doSomething();
},
logic:{
initFirst:function(modelOrView){
// Do not continue if already initiated
if( this.instance !== undefined ) return;
// Write all logic here
this.instance = (function(logic, modelOrView){
// Private variables
var private = "private";
// Public methods
logic.doSomething = function(){
console.log(private, modelOrView);
};
// Private methods
function hidden(){
}
}(this, modelOrView));
}
},
I am trying to organize my JavaScript better. My goal is to have modular architecture that I can break into separate files (sitename.js, sitename.utils.js etc).
I'd like to know what are advantages and disadvantages of these two patterns and which one is more suitable for breaking into modules that live in separate files.
PATTERN #1 (module pattern)
var MODULE = (function () {
//private methods
return {
common: {
init: function() {
console.log("common.init");
}
},
users: {
init: function () {
console.log("users.init");
},
show: function () {
console.log("users.show");
}
}
}
})();
PATTERN #2 (singleton)
var MODULE = {
common: {
init: function() {
console.log("common.init");
}
},
users: {
init: function() {
console.log("users.init");
},
show: function() {
console.log("users.show");
}
}
};
Personally, I recommend an extension of #1, as follows:
var Module = (function(Module) {
// A comment
Module.variable1 = 3;
/**
* init()
*/
Module.init = function() {
console.log("init");
};
// ...
return Module;
})(Module || {});
I like this pattern for a couple reasons. One, documentation (specifically javadoc-style) look more natural when all your functions are declarations rather than a big hash. Two, if your submodules grow in size, it lets you break them into multiple files without any refactoring.
For example, if Module.Users were to go into its own file:
var Module = Module || {};
Module.Users = (function(Users) {
/**
* init()
*/
Users.init = function() {
console.log("Module.Users.init");
};
// ...
return Users;
})(Module.Users || {});
Now "module.js" and "module.users.js" can be separate files, and they'll work regardless of the order they are loaded. Also note the local scoping of the module name - this is very handy if your module name is long, because you can take "MyApp.Users.EditScreen" and refer to it with a variable like "ES" within the scope of your module definition.
The first pattern allows for private variables, methods, etc via closures. For example:
var MODULE = (function () {
var privateStuff = 'This is private';
var doStuff = function(obj) {
console.log('Doing stuff...');
console.log(privateStuff);
};
return {
common: {
init: function() {
console.log("common.init");
doStuff(this);
}
},
users: {
init: function () {
console.log("users.init");
},
show: function () {
console.log("users.show");
}
}
}
})();
privateStuff and doStuff are not properties of the object, and are not available to anything but what's defined inside the function that returns MODULE. So showing an example for how to do this with #2 is not possible.
JS doesn't have the concept of private members, so you can't define them via a regular object literal. So if you need private stuff, go for the first option. If you don't, though, #2 is simpler.
Your code as written is pretty much the same. However, the first form is much easier to work with as you evolve your code, because it allows you to add private variables and functions. The second form doesn't support this, and you nearly always end up wanting the first form eventually.