What's the difference between these two approaches to namespacing? - javascript

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.

Related

Benefit of Immediately-invoked function expression (IIFE) over a normal function

I'm pretty new to javascript and I read about the module pattern to provide some sort of namespace and have both private and public members, for example:
var module = (function() {
var s = "Hello, i'm private and in closure!";
return {
myString : s,
myFunc: function() { alert(s); }
};
})();
I do see the benefits of that, because it gives you some of the advantages of object-oriented programming. But I've seen a lot of examples of an IIFE that doesn't get assigned to a variable. This (as far as I see) has no advantages at all compared to a normal function that you invoke:
1. IIFE
(function() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
})();
2. Normal function
function Initialize() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
}
Initialize();
They both have private variables that avoid the need of creating global variables and they both execute without returning any value to a variable.
Although the second one gives you the option of choosing a good name that says a lot more than a potential large IIFE without the name, leaving the reader to find out what's happening. The answer I see everywhere is 'to avoid namespace pollution' but both approaches do that, the first one is just a bit harder to understand?
In short:
What is the benefit of using an IIFE over a normal function that I'm missing? Why should I use them?
Sometimes you need to define and call function at the same time and only once so in this case anonymous function helps you. In such situations giving functions a name and then calling them is just excess.
Further sometimes you wants to create a namespace for your variables. So anonymous functions helps you there too. For example
(function($) {
$.fn.pluginName = function(opt) {
// implementation goes here...
}
}(jQuery));
In above case you can safely use $ as jQuery synonym in your code.
If you define a function with name as shown below, then it will create global variable with function name as you defined.
function myFunction() {
// function code goes here.
}
myFunction();
But if you define it without name then it won't create any global variable and your global namespace will not be polluted.
(function myFunction() {
// function code goes here.
}());
Function with names are useful only when you need to call them from different places in your code.

Global variables in Javascript (jQuery)

So this is the first time I am using Javascript in a much more powerful context, having a thick client and doing much of the heavy-lifting through javascript in itself. I am using jQuery, and a lot of the code is getting muddy at the moment coz it's all just a bunch of functions.
Turns out for some of my functions, I required variables to be passed through multiple functions with their value being maintained. The obvious way of doing this is by declaring them outside of the scope of the function and then have the function manipulate it the way it ought to . (These variables are objects and not primitive type, so I guess javascript being pass by reference, this works).
For instance, I probably have something like this
var node = //init with some value;
$(document).ready(setup);
function setup()
{
A();
B();
}
function A()
{
// operate on var node
}
function B()
{
// operate on var node
}
This is obviously a scaled down version of my code, but captures the way I deal with global variables. My question is, is there a more elegant way to do the above ?
Thanks
Any reason why you can't do:
$(document).ready(function() {
var node = //init with some value;
setup(node);
function setup(node) {
A(node);
B(node);
}
function A(node) {
// operate on var node
}
function B(node) {
// operate on var node
}
});
In general, using global variables and functions is a bad idea and should be avoided wherever possible.
Note that while you appear to have been asking specifically about node, your functions setup, A and B are also all global variables in your version.
The simplest approach would be to put all these declarations inside an anonymous function:
$(document).ready(function() {
var node = ...;
function A() {
...
}
function B() {
...
}
function setup() {
A();
B();
}
setup();
});
Only use one global variable (or as few as possible). Make any functions or objects members of your one global variable.
Douglas Crockford says
An objective measure of the quality of a JavaScript program is How
many global variables and global functions does it have? A large
number is bad because the chance of bad interactions with other
programs goes up. Ideally, an application, library, component, or
widget defines only a single global variable. That variable should be
an object which contains and is the root namespace for all of your
stuff.
Yahoo’s single global is YAHOO. It is spelled in all caps to identify
it as something special, since all lower case is ordinary and initial
caps indicates a constructor. Being in all caps, it is unlikely that
someone would use it accidentally, which further reduces the
likelihood of collision.
http://www.yuiblog.com/blog/2006/06/01/global-domination/
Also, you can create objects to further organize your code.
GLOBAL.myObject = {};
GLOBAL.myObject.myFunction = ...
I prefer the "revealing module" pattern:
var myApp = (function () {
// privates
var node;
var a = function () {
// operate on node
};
var b = function () {
// operate on node
};
// publics
var init = function () {
// initialization stuff
a();
b();
};
return {
init: init
};
})();
$(document).ready(function () {
myApp.init();
});
This way you only ever have one global, myApp, which stores everything else your app needs.
I think it makes the code harder to understand, I'd much rather take the variable in as an argument and have it as a return.
$(function(){
var outcome = multiply(add(5));
});
function add(num)
{
return num+1;
}
function multiply(num)
{
return num*5;
}
If you feel like you absolutely want to have global variables wrap your stuff in a closure so it doesn't actually go to a global scope.
ie,
(function(){
var a; // can be used in any functions within this closure, but not polluting window
function A()
{
a = 'blah';
}
})();
There are many. For instance, objects.
// jQuery shorthand for "wait till DOM ready"
$( function() {
// create node object
var node = {
id: /* some value */,
setup: function() {
this.A();
this.B();
},
A: function() {
// operate on this.id
},
B: function() {
// operate on this.id
}
};
// setup node object
node.setup();
} );
Global variables are trouble waiting to happen. Don't dirty up your global namespace. Javascript is an object oriented language, use objects. Notice your object can have a property that you can reference with the this keyword from within the objects methods.

The way of good scoping in JavaScript

I am not a really good JavaScript user but I can get things done with it. I am not proud of the code I have written in JavaScript, so I decided to change that. Here is my first step:
I am trying create my own library for a project and the below is the initial structure.
window.fooLib = {};
(function (foo) {
"use strict";
foo.doSomeStuff = function(param1) {
console.log(new AccommProperty(param1));
}
//some internal function
function AccommProperty(nameValue) {
var _self = this;
_self.name = nameValue;
}
}(fooLib));
I used immediately invoked function expression here to initialize my variable. In this case it is fooLib.
I am not sure if I should do some other things to make window.fooLib more safe. I mean it can be overridden by any other code which will run after my code if I understand JavaScript correctly.
What are your thoughts?
If you want to prevent overwriting your variables, you may use Object.defineProperty() with writable:false, configurable:false. In your case:
(function () {
"use strict";
var foo = {};
//some internal function
function AccommProperty(nameValue) {
var _self = this;
_self.name = nameValue;
}
foo.doSomeStuff = function(param1) {
console.log(new AccommProperty(param1));
}
Object.defineProperty(window, "foolib", {value:foo});
}());
Still, there is no good reason for that. It would need EcamScript 5.1 to work, and there are no shims around; maybe something with getters/setters to prevent overwriting with the = operator.
But also, there should be no need to make your library un-overwritable. Just don't use code on your site that overrides the lib. Or maybe someone even wants to overwrite your functions with another, better lib with the same interface?
If the question is about a library to be shared, with possible namespace conflicts to others, you may have a look at jQuery.noConflict.
Every JavaScript object can be overriden. This is the nature of JavaScript and it is impossible to change it. So you cannot make your code safe in that sense.
As for selfinvoked functions: you should use them when you want to have local variables but viisible to all your functions. So in your case AccommProperty is such variable. Defining doSomeStuff inside scope makes no difference unless doSomeStuff will use variables defined inside scope.
So when you want to hide variables from user and/or you need globals and you are affraid of name conflicts use selfinvoked functions.
I am not sure if I should do some other things to make window.fooLib more safe. I mean it can be overridden by any other code which will run after my code if I understand JavaScript correctly.
You could try making window.fooLib a local variable instead. Using closures and nested functions one can emulate a namespace where you can put all your data instead of putting it into the global scope or attaching it to window object:
(function() {
// all functions nested in foo() have access to fooLib.
fooLib = {}
fooLib.doSomeStuff = function(param1) {
console.log(param1);
console.log(fooLib);
}
//some internal function
function AccommProperty() {
console.log(fooLib);
}
}());
See Javascript Closures: Encapsulating Related Functionality for more details.

Accessing a function defined inside a function from the global scope?

Long story short, I have a long code that uses jQuery. Lots of files, functions, etc. A less than ideal amount of our users are having issues with our code because some addons, toolbars and the like they have installed breaks our JavaScript code because of jQuery gets included twice and nasty stuff like that.
I thought I could just
Include jQuery
Use $.noConflict
Then include the whole rest of my code between something like:
.
(function($) {
// All of my code goes here.
})(jQuery);
I haven't checked if this fixes our issues with those users, but it does work. The problem is, in one part of the site (image upload) we have an iframe that needs to call some of those functions defined in our big chunk of code. I've tried putting those functions out of this unnamed function call, but it uses, on itself, other functions which have to be there.
Any idea or workaround of how could I be able to access functions defined inside that function (shown above) from a code that's outside of it?
Thanks!
You cannot access a function context from the "outside world". Well, to be accorate you could do it in some older js engines which allowed for accessing .__parent__ attributes, but that is old'n'busted and no longer available.
However, you would need to either expose some functions within your closure, or you creating a namespace object where you write all of your logic in (which also has to be available in the parent context).
So I'd suggest something like
(function( $ ) {
function myFunc() {
// do stuff
}
function anotherFunc() {
}
window.myFunc = myFunc; // expose myFunc globally
}( jQuery ));
Maybe even better:
var myNameSpace = { };
(function( $ ) {
myNameSpace.myFunc = function() {
// do stuff
};
}( jQuery ));
// somewhere else
myNameSpace.myFunc();
It is not an ideal practice, but you can declare those functions in the global scope.
(function($) {
globalFunct = function (arg1, arg2) { // Don't use var keyword
...
};
})(jQuery);
It isn't ideal because you can run into naming collisions, much like you are observing with jQuery. Improve upon this approach by putting all of your globally-accessible methods in a "package." Choose a unique name for it. This will prevent collisions.
// Somewhere outside of your anonymous function, in the global scope
var myPackage = {};
(function($) {
myPackage.globalFunct = function (arg1, arg2) {
...
};
})(jQuery);
Then call that method by invoking myPackage.globalFunct().
Why are you wrapping your code in a call to the jQuery function object which you pass in to your self-executing anonymous function; are you meaning to create a jQuery object from all of your code?
In order to expose your code to the outside world, you need to assign your functions and objects to an object which is outside of the scope of your code, such as the window object.
For example, if you had created an object containing various methods and properties that you wanted to expose, you could do this:
//Your self-executing anonymous function
(function($)
{
//Object which contains various useful methods and properties
var useful = {...};
//Expose it to the outside world
window.Useful = useful;
})(jQuery);
EDIT: as others have noted, it is not an ideal solution as you will indeed run into naming collisions if you are not careful. Also, using an object external to your anonymous function as a namespacing object (as others have stated) is my preferred method
Yes, you can "export" the function from within a closure:
Yes, you can "export" the function from within a closure:
(function() {
function a() {
console.log("a");
}
function b() {
a();
console.log("b");
}
// make b globally available
window.b = b;
})();
b();
window.PARTY_CATS_jQuery = jQuery.noConflict(true);
(function($) {
$(function() {
// All of my code goes here.
});
})(COMPANY_NAME_jQuery);
Then just use PARTY_CATS_jQuery in your global functions
If you feel PARTY_CATS_ is not a unique enough name pick something safer like BABY_KILLER_jQuery

How to create public and private members?

I'm a bit confused, how can I create public and private members.
My code template so far is like:
(function()){
var _blah = 1;
someFunction = function() {
alert(_blah);
};
someOtherFunction = function() {
someFunction();
}
}();
You may want to use the Yahoo Module Pattern:
myModule = function () {
//"private" variables:
var myPrivateVar = "I can be accessed only from within myModule."
//"private" method:
var myPrivateMethod = function () {
console.log("I can be accessed only from within myModule");
}
return {
myPublicProperty: "I'm accessible as myModule.myPublicProperty."
myPublicMethod: function () {
console.log("I'm accessible as myModule.myPublicMethod.");
//Within myProject, I can access "private" vars and methods:
console.log(myPrivateVar);
console.log(myPrivateMethod());
}
};
}();
You define your private members where myPrivateVar and myPrivateMethod are defined, and your public members where myPublicProperty and myPublicMethod are defined.
You can simply access the public methods and properties as follows:
myModule.myPublicMethod(); // Works
myModule.myPublicProperty; // Works
myModule.myPrivateMethod(); // Doesn't work - private
myModule.myPrivateVar; // Doesn't work - private
You don't. You can rely on convention, prepending _ to your private attributes, and then not touching them with code that shouldn't be using it.
Or you can use the function scope to create variables that can't be accessed from outside.
In javascript every object member is public. Most popular way of declaring the private field is to use the underscore sign in it's name, just to make other people aware that this is private field:
a = {}
a._privateStuff = "foo"
The other way to hide the variable is using the scopes in javascript:
function MyFoo {
var privateVar = 123;
this.getPrivateVar = function() {
return privateVar;
}
}
var foo = new MyFoo();
foo.privateVar // Not available!
foo.getPrivateVar() // Returns the value
Here's the article that explains this technique in details:
http://javascript.crockford.com/private.html
Three things:
IIFEs:
It seems like you need to refresh your knowledge regarding this pattern. Have a look at this post before using an IIFE again.
Global public vs. Safe public:
Skipping var keyword with someFunction and someOtherFunction leads to registration of these function objects in the global scope, i.e., these functions can be called and reassigned from anywhere in the code. That could lead to some serious bugs as the code grows bigger in size. Instead, as Daniel suggested, use the module pattern. Though you can use other methods too like Constructors, Object.create(), etc, but this is pretty straightforward to implement.
/* create a module which returns an object containing methods to expose. */
var someModule = (function() {
var _blah = 1;
return {
someFunction: function() {},
someOtherFunction: function() {}
};
})();
/* access someFunction through someModule */
someModule.someFunction();
// ...
// ....
/* after 500+ lines in this IIFE */
/* what if this happens */
someFunction = function() {
console.log("Global variables rock.");
};
/* Fortunately, this does not interfere with someModule.someFunction */
Convention and scope combined:
We cannot expect from every developer to follow the underscore or the capitalization convention. What if one of them forgets to implement this technique. Instead of just relying upon the convention (_private, GLOBAL) and the scope (function scoping), we can combine both of them. This helps in maintaining consistency in coding style and provides proper member security. So, if next time somebody forgets to capitalize their globals, the console (in strict mode) can prevent the world from ending.
Javascript doesn't have true private members. You have to abuse scope if your really need privacy.
I hope this URL will solve your problem...see that...
http://robertnyman.com/2008/10/14/javascript-how-to-get-private-privileged-public-and-static-members-properties-and-methods/

Categories

Resources