I'm frequently using this structure:
var example = (function () {
function privateFn2 () {
...
}
function privateFn1 () {
...
}
return {
publicMethod1: function () {...
},
publicMethod2: function () {...
}
};
}());
What I want to know is this: If privateFn1 is the only function/method that calls privateFn2, is it regarded as better practice to set it up as follows?
EDITED for clarity
var example = (function () {
function privateFn1() {
function privateFn2() {
}
...
privateFn2();
}
return {
publicMethod1: function () {...
},
publicMethod2: function () {...
}
};
}());
This is a wildly simplified example, of course. The issue is that I have lots of private functions, and I'm wondering whether nesting is well- or poorly-regarded. I recognise it is quite possibly a matter of preference, but any advice will be gratefully received.
Thanks.
It depends on the situation. If you have several private functions that are only relavent to yet another private function, then perhaps this is a situation where the object or class is packaging more functionality then it should be.
Here are some questions to ask:
Do these private functions have side effects? That is, are they
manipulating any closed over properties? If not, is this some generalized
logic that could be implemented statically and included
separately? Or, are these private functions manipulating a subset of
properties that could be moved to another class or object?
Are the private functions simple task specific helper functions to be used within
a larger algorithm or control function; such as a filter function for sorting an
array, or some other kind of iteration callback? If so, then it may be in-fact
cleaner to nest those functions inside and keep them out of scope of the main
object. Will any other code need these functions?
How many times will the main private function be called? If it will be called very
frequently (inside a loop or on a timer interval) then nesting the
private functions inside could incur a measurable overhead --
which would have otherwise been negligible had the private function
been called only occasionally.
There are always trade-offs to consider, thinking about these questions will help you decide what is best for your particular situation.
I would avoid your second example. Every time privateFn1 gets called, it redefines privateFn2. Why not just do it once? You might even need to use it somewhere else later on.
However, if you really want to hide privateFn2, a better solution is this:
var privateFn1 = (function () {
function privateFn2() {
// ...
}
return function () {
privateFn2();
// ...
};
})();
Related
So I can't seem to find astraight answer on this, only vague examples of multiple variations where similar plugin/method declarations are used. I know that by saying
$.fn.myPlugin
I am defining a publicly available plugin method that can be executed on any valid jQuery object where the fn denotes the prototype. My question is then, by defining a method, either inside of my main plugin like so
$.fn.myPlugin.methodName
or outside of my plugin like so
$.something.methodName //where 'something' is in place of 'fn'
does this affect it being a public private/method? and if each is a different type of declaration, what is the difference.
The backstory of why I would like to know, to give some context to the situation, is that I want to define one main plugin that can be called and have run normally, however if the end user wants to redefine some method I have allowed to be public then they can do that. If I have any methods that I don't want the user to redefine but instead provide callbacks so they can hook into it, then I want to make that method private.
Anything set on $.whatever will be public, and therefore able to be modified by other developers.
If you want private methods, you should create a closure.
(function() {
function init(jqObj) { ... } // do magic here
$.fn.myPlugin = function() { init(this); } // avoid exposing core method
$.fn.myPlugin.publicMethod = function() { ... }
function privateMethod() { ... }
})();
Im designing an API that requires my users to download a javascript file from my server and then load it on their pages. Inside this file there is a function call generic(), if my users include this js and for some reason they have a piece of js on their page where there is another function call generic() this will represent an issue. Im not a front end dev, I know that with php you can solve this creating a class and putting all your functions inside, so you can call them like $myclass->myfunction();, but how can i solve this on js? Is this even a good approach on js? (no jquery please.)
You will obviously always have to expose at least one identifier globally, but a common approach is to wrap everything in an immediately-invoked function expression:
var YourNamespace = (function () {
var privateData = 10; // Not accessible outside the IIFE
// Expose public properties (these functions can access the private data)
return {
someMethod: function () {
// Do stuff
},
anotherMethod: function () {
// More stuff
}
};
}());
This will expose a single identifier, YourNamespace, as an object with properties that can be used as methods. You can use it like this:
YourNamespace.someMethod();
Wrap your code inside a wrapper object/ or function.
var MyLibrary = {
global1: 123,
global2: 'abc',
doSomething: function(a){
// ...
},
somethingElse: function(b){}
};
If u are looking for Encapsulation in Javascript, then u are looking for Closures
I've got the first file in my code directory as follows
myNamespace.js
var myNamespace = {};
Then my subsequent files can look as one of the two following ways.
first
(function (ns) {
ns.DoStuff = function(){
// do stuff
}
})(myNamespace);
second
myNamespace.DoStuff = function(){
//do stuff
}
So what is the difference between these two methods? Both seem to work for me. Is there a more generally accepted convention?
sorry, still new to javascript
Your first approach will not work. It would create DoStuff on the global object (most likely window). You would need to replace this with ns, after you did that, there is no difference between the two approaches.
The former will have the adventage that you might be able to closure all your application/file related stuff into that outer self-invoking closure function. So you won't clobber the global namespace.
(function (ns) {
var foo = 10,
bar = 42;
ns.DoStuff = function(){
console.log('foo is ', foo, ' and its not available globally');
}
})(myNamespace);
You have an error in your first one, you've used this where I'm pretty sure you meant ns:
ns.DoStuff = function() {
};
Leaving that aside, your first approach tends to be better because you've created a nice little scoping function for yourself, which allows you to have private data and functions available to all of the public methods you create on your namespace, without making them globals. E.g.:
(function(ns) {
function privateFunction() {
}
ns.DoStuff = function() {
privateFunction(); // <=== works fine
};
})(myNamespace);]
privateFunction(); // <=== doesn't work, because it's private
I like doing it that way partially because I have thing against anonymous functions, and so I wouldn't define DoStuff as above, but rather like this:
(function(ns) {
ns.DoStuff = Namespace$DoStuff;
function Namespace$DoStuff() {
}
})(myNamespace);
Now the function I've assigned to myNamespace.DoStuff has a proper name, which helps me out when I'm debugging my code. But that name doesn't pollute the global namespace, which helps me stay sane and avoid conflicts with other code.
I was searching over the Internet for good JS practices and found an interesting one (that sadly, I don't understand it entirely)
myNameSpace = function(){
var current = null;
function init(){...}
function change(){...}
function verify(){...}
return{
init:init,
change:change
}
}();
Where can I use this name space?
How can I use the names pace?
Is it really good idea to use this instead of Global?
Source of script: http://dev.opera.com/articles/view/javascript-best-practices/
You can also use a code like this, that lets you write OO JavaScript code. You should group only cohesive functions in one unit and build more objects like this as needed.
Note that function buildFullName is a private function, since it can't be accessed from outside.
I agree with you that is confusing, without previous JavaScript knowledge. The fact is that a function is a first class Object in JavaScript. You can nest functions within functions, they can have variables, and there are so many ways to combine them, there is no standard way like in Java. I think the article JavaScript Closure 101 can help you clear things up a bit.
/** This is our Object definition and constructor */
function Person(fname, lname) {
this.firstName = fname;
this.lastName = lname;
}
/** Anonymous function to avoid polluting the global namespace */
(function () {
/** This function will be defined public, we prefix the class name */
function Person_toString() {
//call buildFullName passing this, we could also call the function
//as buildFullName(), and it would work, but wouldn't have 'this'
return buildFullName.call(this);
}
/** Another public function */
function Person_buildGreeting() {
return "Hi " + this.firstName;
}
/** This function is private! */
function buildFullName() {
return this.firstName + " " + this.lastName;
}
/** Here we augment the Object with public functions */
Person.prototype = {
toString: Person_toString,
buildGreeting: Person_buildGreeting
};
})(); //execute the anonymous function immediately
Example usage:
var p1 = new Person('Jenny', 'Fairview');
alert("toString()=" + p1.toString());
alert("buildGreeting()=" + p1.buildGreeting());
That was one poor article, at least the section on avoiding globals. These things arise when your code gets so incredibly large that eventually you will come to give it a prefix, for example dojo. All/Most dojo functions start with dojo. so when you load it, it doesn't overwrite your functions (of course this assumes you don't have a function or variable called dojo).
If you have 1000 functions in the form
function init(){...}
function run(){...}
function start(){...}
The argument they're making is that it's easier to do
packageName = function{
function init(){...}
function run(){...}
function start(){...}
return {
init : init ,
run : run ,
start : start
}
than
packageName = function{
init : function init(){...} ,
run : function run(){...} ,
start : function start(){...}
}
I prefer the latter. It's cleaner, more concise, and less confusing.
You can go a little further and use CommonJS or AMD modules to construct your application and avoid globals pretty much altogether. Dojo is moving in this direction, but has not yet migrated away from using dojo.*
I generally write code that looks like this (but with many more handlers).
$(document).ready(function() {
$("#next").click(function() {
doStuff();
});
$("#prev").click(function() {
doSomeOtherStuff();
});
$("#link").hover(function() {
doSomeTotallyOtherStuff();
});
});
Is this the best way of doing this? Should I do it differently? Paul Irish's presentation suggests it's a bad idea. Is that true?
We like to use the object literal pattern and named functions. I'd rewrite your example like this:
$(function() {
Example.somegrouping.init();
});
var Example.somegrouping = {
init: function() {
// set up listeners
$("#next").click(this.onNextClick);
$("#prev").click(this.onPrevClick);
$("#link").hover(this.onLinkHover);
},
onNextClick: function() {
// do some stuff
},
onPrevClick: function() {
// do some stuff
},
onLinkHover: function() {
// do some stuff
}
};
Why? Well, it makes it easier to reuse event handlers in other places without resorting to triggers. The naming of the function can help self-document your code. Testing/debugging is easier. The object literal only adds one entry to the global namespace, so there is little chance for collisions with other scripts your page might be using.
One reason that it's useful to define your functions the old boring way is that you get names to look at in stack traces.
$(function() {
function nextClickHandler() { ... };
$('#next-button').click(nextClickHandler);
});
It's not safe to use a function name in a function expression:
$('#next-button').click(function nextClickHandler() { // DO NOT DO THIS
});
which is sort-of unfortunate but there you go.
This should be fine as long you don't do it in a loop or some other code that runs more than once (i.e. a recurring function call). Otherwise there's not much difference between one anon function and one named function. it's when you have 100 identical anonymous functions that's a problem.
ex:
$("#someID").click(function(){})
is okay,
for (var i in somelistofIDs) {
$(i).click(function(){})
}
is not, because you've created 100 anonymous functions instead of one named function.
EDIT
of course, if you're wrapping a single function call in a closure, you're doing it wrong, you can just pass the function itself.