Private functions in JavaScript - javascript

In a jQuery-based web application I have various script where multiple files might be included and I'm only using one of them at a time (I know not including all of them would be better, but I'm just responsible for the JS so that's not my decision). So I'm wrapping each file in an initModule() function which registers various events and does some initialization etc.
Now I'm curious if there are any differences between the following two ways of defining functions not cluttering the global namespace:
function initStuff(someArg) {
var someVar = 123;
var anotherVar = 456;
var somePrivateFunc = function() {
/* ... */
}
var anotherPrivateFunc = function() {
/* ... */
}
/* do some stuff here */
}
and
function initStuff(someArg) {
var someVar = 123;
var anotherVar = 456;
function somePrivateFunc() {
/* ... */
}
function anotherPrivateFunc() {
/* ... */
}
/* do some stuff here */
}

The major difference between these two approaches resides in the fact WHEN the function becomes available. In the first case the function becomes available after the declaration but in the second case it's available throughout the scope (it's called hoisting).
function init(){
typeof privateFunc == "undefined";
var privateFunc = function(){}
typeof privateFunc == "function";
}
function init(){
typeof privateFunc == "function";
function privateFunc(){}
typeof privateFunc == "function";
}
other than that - they're basically the same.

this is a model that helped me to manage modules in javascript:
base.js:
var mod = {};
mod.functions = (function(){
var self = this;
self.helper1 = function() {
} ;
self.helper2 = function() {
} ;
return self;
}).call({});
module_one.js
mod.module_one = (function(){
var
//These variables keep the environment if you need to call another function
self = this, //public (return)
priv = {}; //private function
priv.funA = function(){
}
self.somePrivateFunc = function(){
priv.funA();
};
self.anotherPrivateFunc = function(){
};
// ini module
self.ini = function(){
self.somePrivateFunc();
self.anotherPrivateFunc();
};
// ini/end DOM
$(function() {
});
return self; // this is only if you need to call the module from the outside
// exmple: mod.module_one.somePrivateFunc(), or mod.module_one.ini()
}).call({});

Related

what is the best javascript access performance with using window or not

I have several modules. and I'm wondering how to declare these modules.
if there are many modules and access each others function,
What is the better way between 'var module' and 'window.module'?
and 'window.moule.somefunction' and 'module.somefunction' in otherModules function.
for example,
// window.menu =
var menu = function(){
var menus = null;
// + many other functions, variables
function init(){
getMenu();
};
function getMenu(){
menus = $.ajax(...);
};
function doOrder(idx){
var item = menus[idx];
// window.order.doOrder(item)
order.doOrder(item); // access other module
};
return{init:init};
}();
// window.order =
var order = function() {
var someVariable = null;
// + many other functions, variables
function init() {
// initiallize
};
function doOrder() {
// do order
};
return {doOrder:doOrder};
}();

avoid needing to declare 'var me = this' for javascript prototype functions

Currently, I create objects in javascript by declaring a construction (regular function) then add methods to the prototype like so
function Test(){
}
Test.prototype.test1 = function(){
var me = this;
}
However, I would like to avoid having to declare var me = this at the top of every function. The following seems to work, but seems like it would be very inefficient:
$(document).ready(function(){
var n = 0;
(function(){
function createTest(){
var me;
function Test(){
this.n = n;
this.testArr = [1, 2, 3, 4];
n++;
}
Test.prototype.test1 = function(){
me.test2();
};
Test.prototype.test2 = function(){
alert(me.n);
$.getJSON('test.php', {}, function(reply)
//want to be able to use 'me' here
me.newField = reply;
});
};
var t = new Test();
me = t;
return t;
}
window['createTest'] = createTest;
})();
var t = createTest();
t.test1();
var t2 = createTest();
t2.test1();
t.test1();
});
This code outputs the expected, but is it actually as inefficient as it looks (the Test object being re-declared every time you call createTest())?
Anyhoo, this would seem a bit hacky... is there a completely different way to do this that is better?
EDIT: The real reason I would like to do this is so that callbacks like the one in test2 will have references to the correct this.
What you can do is bind the current this value to a function and store a copy somewhere. (For the sake of efficiency.)
if (!Function.prototype.bind) {
// Most modern browsers will have this built-in but just in case.
Function.prototype.bind = function (obj) {
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () { },
bound = function () {
return self.apply(this instanceof nop ? this : (obj || {}),
args.concat(slice.call(arguments)));
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
}
function Test(n) {
this.n = n;
this.callback = (function () {
alert(this.n);
}).bind(this)
}
Test.prototype.test1 = function () {
this.test2();
}
Test.prototype.test2 = function () {
doSomething(this.callback);
}
function doSomething(callback) {
callback();
}
var t = new Test(2);
t.test1();
I realize your question was not tagged with jQuery, but you are using it in your example, so my solution also utilizes jQuery.
I sometimes use the $.proxy function to avoid callback context. Look at this simple jsfiddle example. Source below.
function Test(){
this.bind();
}
Test.prototype.bind = function(){
$('input').bind('change', $.proxy(this.change, this));
// you could use $.proxy on anonymous functions also (as in your $.getJSON example)
}
Test.prototype.change = function(event){
// currentField must be set from e.target
// because this is `Test` instance
console.log(this instanceof Test); // true
console.log(event.target == $('input')[0]); // true
this.currentField = event.target; // set new field
};
function createTest(){
return new Test();
}
$(function(){ // ready callback calls test factory
var t1 = createTest();
});
Most of the time, I just declare a local variable that references this, wherever I need a reference to this in a callback:
function Foo() {
}
Foo.prototype.bar = function() {
var that=this;
setTimeout(function() {
that.something="This goes to the right object";
}, 5000);
}
Alternatively, you can use bind() like this:
Function Foo() {
this.bar = this.bar.bind(this);
// ... repeated for each function ...
}
Foo.prototype.bar = function() {
}
What this gives you is that every time you create a new Foo instance, the methods are bound to the current instance, so you can use them as callback functions for setTimeout() et al.

Why aren't options being overridden?

In my module pattern, options are 'undefined' for some reason.. does anyone see why they aren't being passed in properly?
Framework.MyModule = (function(options) {
var defaults = {
someOption : 1,
stuff : 2
};
if (!options) {
var options = defaults;
} else {
for (var index in defaults) {
if (typeof options[index] == 'undefined')
options[index] = defaults[index];
}
}
var module = {};
// Initialize
_something();
// Private Methods
function _something() {}
// Public Methods
module.click = function() {};
return module;
})();
... docready function ...
var options = {
someOption : 9,
stuff : 10
};
Framework.MyModule(options);
... end doc ready ...
Please see the fiddle: http://jsfiddle.net/kWHEZ/1/
var options = { /* ... */};
Framework.MyModule = (function(options) {
/* .. options are undefined ... */
})();
Framework.MyModule = (function(options) {
/* .. options are defined... */
})(options);
Now if you want the ability to add private/public variables AND still pass options you will need to make it so the a constructor method is returned with your public object - thus not passing options in the function that is run immediately. Because lets be honest .. this doesn't really make sense.
You could do something like this:
var Module = {};
Module.Foo = (function($){ // jQuery is accessible as $
var _private = {
defaults: {
url: '/default-url', container: '#dummy'
},
foos: []
};
return function(o){ // returns constructor
// other _private variables are accessible here
var opts = $.extend({}, _private.defaults, o);
var self = { // public return object
load: function(){
$(opts.container).load(opts.url);
}
};
_private.foos.push(self);
return self;
};
})(jQuery); // scope global variables
var foo1 = Module.Foo({
url: '/test.php',
container: '#success'
});
var foo2 = Module.Foo({
url: '/test2.php',
container: '#success2'
});
foo1.load();
foo2.load();
You're not passing in any options to the anonymous function call.
your call would have to end with })(options); if you want it to use custom options.
You're executing the function immediately. That function returns module, which is an object, not a function. Did you mean instead to return a function?
Then call it using:
Framework.MyModule(options);

JavaScript Namespace

I want to create a global namespace for my application and in that namespace I want other namespaces:
E.g.
Dashboard.Ajax.Post()
Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();
I also want to place them in seperate files:
Ajax.js
RetrieveContent.js
However I have tried using this method, however it won't work because the same variable name is being used for the namespace in 2 seperate places. Can anyone offer an alternative?
Thanks.
You just need to make sure that you don't stomp on your namespace object if it's already been created. Something like this would work:
(function() {
// private vars can go in here
Dashboard = Dashboard || {};
Dashboard.Ajax = {
Post: function() {
...
}
};
})();
And the RetrieveContent file would be defined similarly.
Here is a very good article on various "Module Patterns" in JavaScript. There is a very nice little section on how you can augment modules, or namespaces and maintain a cross-file private state. That is to say, the code in separate files will be executed sequentially and properly augment the namespace after it is executed.
I have not explored this technique thoroughly so no promises... but here is the basic idea.
dashboard.js
(function(window){
var dashboard = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
window.Dashboard = dashboard;
})(window);
dashboard.ajax.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.ajax = function(){
// ...
}
return my;
}(dashboard || {}));
dashboard.retrieveContent.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.retrieveContent = function(){
// ...
}
return my;
}(dashboard || {}));
The Yahoo Namespace function is exactly designed for this problem.
Added:
The source of the function is available. You can copy it into your own code if you want, change the root from YAHOO to something else, etc.
There are several libraries that already offer this sort of functionality if you want to use or examine a pre-baked (that is, a tested) solution.
YUI.attribute and YUI.base
dojo.mixin
underscore.extend
jQuery.extend
goog.provide and goog.object.extend
The simplest and most bug free one to get going with is probably jQuery.extend, with the deep argument set to true. (The reason I say it is bug free is not because I think that jQuery.extend suffers from less bugs than any of the other libraries -- but because it offers a clear option to deep copy attributes from the sender to the receiver -- which most of the other libraries explicitly do not provide. This will prevent many hard-to-diagnose bugs from cropping up in your program later because you used a shallow-copy extend and now have functions executing in contexts you weren't expecting them to be executing in. (If however you are cognizant of how you will be extending your base library while designing your methods, this should not be a problem.)
With the NS object created, you should just be able to add to it from where ever. Although you may want to try var NS = NS || {}; to ensure the NS object exists and isn't overwritten.
// NS is a global variable for a namespace for the app's code
var NS = NS || {};
NS.Obj = (function() {
// Private vars and methods always available to returned object via closure
var foo; // ...
// Methods in here are public
return {
method: function() {
}
};
}());
You could do something like this...
HTML page using namespaced library:
<html>
<head>
<title>javascript namespacing</title>
<script src="dashboard.js" type="text/javascript"></script>
<script src="ajax.js" type="text/javascript"></script>
<script src="retrieve_content.js" type="text/javascript"></script>
<script type="text/javascript">
alert(Dashboard.Ajax.Post());
alert(Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent());
Dashboard.RetrieveContent.Settings.Timeout = 1500;
alert(Dashboard.RetrieveContent.Settings.Timeout);
</script>
</head>
<body>
whatever...
</body>
</html>
Dashboard.js:
(function(window, undefined){
var dashboard = {};
window.Dashboard = dashboard;
})(window);
Ajax.js:
(function(){
var ajax = {};
ajax.Post = function() { return "Posted!" };
window.Dashboard.Ajax = ajax
})();
Retrieve_Content.js:
(function(){
var retrieveContent = {};
retrieveContent.RefreshSalespersonPerformanceContent = function() {
return "content retrieved"
};
var _contentType;
var _timeout;
retrieveContent.Settings = {
"ContentType": function(contentType) { _contentType = contentType; },
"ContentType": function() { return _contentType; },
"Timeout": function(timeout) { _timeout = timeout; },
"Timeout": function() { return _timeout; }
};
window.Dashboard.RetrieveContent = retrieveContent;
})();
The Dashboard.js acts as the starting point for all namespaces under it. The rest are defined in their respective files. In the Retrieve_Content.js, I added some extra properties in there under Settings to give an idea of how to do that, if needed.
I believe the module pattern might be right up your alley. Here's a good article regarding different module patterns.
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
I highly recommend you use this technique:
https://github.com/mckoss/namespace
namespace.lookup('com.mydomain.mymodule').define(function (ns) {
var external = namespace.lookup('com.domain.external-module');
function myFunction() {
...
}
...
ns.extend({
'myFunction': myFunction,
...
});
});
I've been using this pattern for a couple of years; I wish more libraries would do the same thing; it's made it much easier for me to share code across my different projects as well.
i wrote this function to simplify creating namespaces. Mabey it will help you.
function ns(nsstr) {
var t = nsstr.split('.');
var obj = window[t[0]] = window[t[0]] || {};
for (var i = 1; i < t.length; i++) {
obj[t[i]] = obj[t[i]] || {};
obj = obj[t[i]];
}
}
ns('mynamespace.isawesome.andgreat.andstuff');
mynamespace.isawesome.andgreat.andstuff = 3;
console.log(mynamespace.isawesome.andgreat.andstuff);
bob.js can help in defining your namespaces (among others):
bob.ns.setNs('Dashboard.Ajax', {
Post: function () { /*...*/ }
});
bob.ns.setNs('Dashboard.RetrieveContent', {
RefreshSalespersonPerformanceContent: function () { /*...*/ }
});
Implementation:
namespace = function(packageName)
{
// Local variables.
var layers, layer, currentLayer, i;
// Split the given string into an array.
// Each element represents a namespace layer.
layers = packageName.split('.');
// If the top layer does not exist in the global namespace.
if (eval("typeof " + layers[0]) === 'undefined')
{
// Define the top layer in the global namesapce.
eval(layers[0] + " = {};");
}
// Assign the top layer to 'currentLayer'.
eval("currentLayer = " + layers[0] + ";");
for (i = 1; i < layers.length; ++i)
{
// A layer name.
layer = layers[i];
// If the layer does not exist under the current layer.
if (!(layer in currentLayer))
{
// Add the layer under the current layer.
currentLayer[layer] = {};
}
// Down to the next layer.
currentLayer = currentLayer[layer];
}
// Return the hash object that represents the last layer.
return currentLayer;
};
Result:
namespace('Dashboard.Ajax').Post = function() {
......
};
namespace('Dashboard.RetrieveContent').RefreshSalespersonPerformanceContent = function() {
......
};
Gist:
namespace.js

JavaScript Module Pattern - What about using "return this"?

After doing some reading about the Module Pattern, I've seen a few ways of returning the properties which you want to be public.
One of the most common ways is to declare your public properties and methods right inside of the "return" statement, apart from your private properties and methods. A similar way (the "Revealing" pattern) is to provide simply references to the properties and methods which you want to be public. Lastly, a third technique I saw was to create a new object inside your module function, to which you assign your new properties before returning said object. This was an interesting idea, but requires the creation of a new object.
So I was thinking, why not just use this.propertyName to assign your public properties and methods, and finally use return this at the end? This way seems much simpler to me, as you can create private properties and methods with the usual var or function syntax, or use the this.propertyName syntax to declare your public methods.
Here's the method I'm suggesting:
(function() {
var privateMethod = function () {
alert('This is a private method.');
}
this.publicMethod = function () {
alert('This is a public method.');
}
return this;
})();
Are there any pros/cons to using the method above? What about the others?
Your function has no object context, so this references to the global window object in this case. Every property you assign to this automatically pollutes the global namespace.
(function() {
console.log(this == window); // true
this.publicMethod = function () {
alert('This is a public method.');
}
})();
console.log(publicMethod); // function()
You can explicitly pass it an object to tell which context to use.
var MYAPP = {};
(function() {
// 'this' will now refer to 'MYAPP'
this.publicMethod = function () {
alert('This is a public method.');
}
}).call(MYAPP);
console.log(publicMethod); // undefined
console.log(MYAPP.publichMethod); // function()
Which you can write in somewhat other style:
var MYAPP = (function(my) {
var my;
⋮
return my;
})(MYAPP);
And we arrived to an already discussed pattern. For further details, see Dustin's article on Scoping anonymous functions.
I would recommend the style where you add your public properties and methods to an anonymous object that you then return:
var myModule = (function() {
function privateMethod() { ... }
function publicMethod() { ... }
return { publicMethod: publicMethod };
})();
if you want to publish methods, then do something like:
var export = (function() {
var privateMethod = function () {
alert('This is a private method.');
}
var export = {};
export.publicMethod = function () {
alert('This is a public method.');
}
return export;
})();
Another option is to avoid the this reference altogether. Define a function that creates and returns an anonymous object instead.
function makeThing(someAttribute) {
var privateVariable = 42;
function someMethod() {
return privateVariable;
}
return {
"publicMethodName": someMethod,
"getAttribute": function() {
return someAttribute;
}
};
}
var thing = makeThing(99);
thing.publicMethodName();
thing.getAttribute();
Revealing Module patterns:
var m1 = (function(){ return {method: mthod} })();
var m2 = new function Singleton(){ return {method: mthod} };
var m3 = ({}).prototype = {method: method};
var m4 = ({}).prototype = (function(){ ... })();
var m5 = (function(){}).prototype = {} || (function(){ ... })();
var m6 = (function(extendee){
return extendee.prototype = {attr3: 'attr3'};
})({currentAttr1: 1, currentAttr2: 2});
Also, if you need method-chaining:
var m = (function(){}).prototype = (function(){
var thus = m; // this
console.log('m this-------', thus);
function fn(){
console.log('fn', thus);
return thus;
}
function f(){
console.log('f', thus);
return 'poop';
}
return {f: f, fn: fn};
})();
console.log('M:', m, 'm.fn', m.fn(), 'm.fn.f', m.fn().f());
There's also plenty more ways, and you can protagonize your modules as well.

Categories

Resources