Self-invoking function and params? - javascript

I've seen the next way of writing self-invoking functions:
(function (app) {
app.foo = {
bar: function(){}
};
}(App));
Where App is a global object.
I wonder, why do we need to pass App as a param into a function? Why don't just use this:
(function () {
App.foo = {
bar: function(){}
};
}());
I see only one advantage of using the first way. If we for some reason rename the App object, then we can easily rename the param in brackets and our code will work as it works. But in case of the second way we will probably need to rename App in all places where we use it.
Are there other differences?

It means that the contents of the function – with regards to the app identifier – are agnostic to the global (or parent) scope.
One of the scenarios in which this is done is, for example, with jQuery, when you don't want to assume that the jQuery object is called $ (e.g. if no-conflict mode is on), but you do want to call it by that name. Passing it through an anonymous function like this (i.e. (function($) {})(jQuery)) allows you to generate a locally-scoped alias that doesn't interfere with the external meaning of the name $ in the parent/global scope.

The other answers explain the benefit of having a locally scoped copy. There are a few other benefits too:
As a micro-optimization it reduces scope lookups (it's less expensive to find a local var than a global one).
It can help in the minification process as all your params are reduce to single letter named vars.
It gives you a pseudo dependency management technique...in your example, you know your code is dependent on App.

For example, many libraries use the "$" character as a shortcut for their main function (e.g. JQuery). This is convenient, but can cause a clash when using multiple libraries. So, you could pass JQuery in like this:
(function($) {
// Code
var nav = $('#nav');
// More code
})(JQuery);
That way, you can still use the convenient shortcut, but you can also avoid clashes (as long as you also configure the libraries not to use the "$" shortcut).

You can also use it to redefine global variables locally to ensure they contain whay you expect:
(function($, undefined) { ... })(jQuery);
Where undefined is now the expected undefined. Also see: What is the purpose of passing-in undefined?
Most other uses are well covered in the other answers.

Related

JavaScript Module Pattern written two different ways with same results

I have been developing an app using JavaScript and all of my scripts are using the Module Pattern. Example:
var MyFunction = (function(){
}());
I saw where someone placed the name of the function inside the calling (). Example:
var MyFunction = (function(){
}(MyFunction));
I add this to some of my page and it still ran normal. Can anyone explain why it would be written with the name of the function inside the ()?
Can anyone explain why it would be written with the name of the
function inside the ()?
No. That coder didn't know quite what they were doing. (A lot tends to get left in when someone doesn't want to break working code)
That said, there are some situations where you would pass something into the IIFE, like window or jquery. You'd treat it as an argument on the inside, though.
The two versions you show are equivalent, but the second one is misleading: the parameter of the IIFE is not used.
You might want to pass (and use) an argument to a module IIFE to alias a dependancy:
var myModule = (function(t) {
//...
var someText = t('some.key');
//...
})(translationModule);
Another use which is opposite to your second example is to declare an argument to the IIFE, and pass nothing. This is to make sure that undefined is... undefined:
var myModule = (function(undefined) {
// Here you're safe from bizare third party code which might define 'undefined'.
})();
In his book Learning JavaScript Design Patterns, Addy Osmani shows several variations of the module pattern:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript
Recommended reading.
Cheers!

Why pass jQuery as an argument to (function($){..})(jQuery) closure wrapper, instead of local var?

The closure wrapper (function($){..})(jQuery); is a great way to have local variables instead of global ones. Both $ and any variable and local function defined within the wrapper is visible only within the wrapper, not outside. This is great, and I use it all the time.
(function($){
[..]
})(jQuery);
However, I have been wondering why we pass jQuery (and possibly other stuff) as an argument, instead of using a local variable declaration.
(function(){
var $ = jQuery;
[..]
})();
Wouldn't this work just as fine, and be more transparent?
I see one reason when former way is better:
(function(){
var $ = jQuery;
[..]
var jQuery = foo;
})();
In this example variable "$" will be undefined because of hoisting.
There's an advantage in terms of code length. It saves a few characters (bytes...). It's not much, but if you have to choose between the 2, the first example is shorter.
In the sake of minification, it's also possible (and to some degree common) to use an "unset" variable to serve as an undefined match like this:
(function(r,u){if(r.missingProp===u)alert('undefined!')})({realProp:1})
Since u isn't passed a value during the call, it will equal undefined

How to use the $ alias for jQuery with seveal source files

I am using jQuery in some custom files added to a Wordpress site, and am using this to allow me to use the "$" shortcut:
jQuery(function ($) {
$(selector).bla();
// etc
}
However, if I want to split my code into several files, this construct needs to exist in each file, and then functions from one cannot be called from the other. How to do this? Can I somehow declare certain functions as global?
You might want to look at using requirejs to define modules, then pass the modules in as dependencies. You can also use it to define jQuery as as dependency so that it can be scoped locally with whatever variable name you want.
require(['jquery','somemodule','someothermodule'], function($,module1,module2) {
$(function() {
var mod1 = new module1();
var mod2 = new module2();
...
});
});
You can use something like this:
var myFunc = function($) {
function toExport() {
alert($);
}
return toExport;
}(jQuery);​
Just return resources you need (it can be single function, or object, or anything you want actually.)
jQueryUI is actually written a similar way:
(function( $, undefined ) {
...
}( jQuery ) );
This way the $ is guaranteed to be a synonym for the jQuery function and the keyword undefined will be defined as parameter with an undefined value. The undefined portion actually fixes some nit picky issues with a few browsers since they don't all handle undefined the same way.
You can always declare functions outside the jQuery(function() {...}); construct, in global scope.
You just cannot access the DOM before it is ready, which means you cannot execute those functions outside jQuery(function() {...}); if they access the DOM.
You can also always create a global variable by assigning a value to window property:
window.theanswer = 42;
Adding many values to the global namespace is not a good practice, and other techniques exist to create modular JavaScript to solve this problem. See tvanfosson's answer.

Anonymous closures and global imports

I was reading this article about the module Javascript pattern, but I don't understand what is the benefit of the "Global import".
What is the difference between:
(function () {
alert($('#theForm').attr('method'));
} ());
and
(function ($) {
alert($('#theForm').attr('method'));
} (jQuery));
Both methods has the same effect, so I think I am missing the point here.
What is the point of pass global variables as parameters in the anonymous closure? what are the benefits?
Lots of scripts (such as Prototype and Mootools) also use the $ character. It is therefore sometimes useful to not use that character on a global level. You can do this in jQuery by using jQuery.noConflict(). You then have to use jQuery to do jQuery selections and the like.
If, however, you have a section of code (a "module", perhaps) that you know will only use jQuery, you can redefine $ for that section of code only using that pattern. The object known as jQuery outside the function is now known as $ inside the function:
(function($) { // the first parameter is known as $
// inside the function, you can access jQuery by the name $
}(jQuery)); // pass jQuery as the first argument
By the second version, you are ensuring that you may use the dollar-sign $ for jquery. Otherwise, you could get into trouble, when you import a second javascript library that also uses the dollar sign as an alias (prototype for example).
So by the second version, you always ensure there will be no conflicts, by passing in the unique name (jQuery in this case).
A simplified example to explain this would be as follows.
var jqueryCloneLibrary = {libName : 'jqClone_1.1.1',size : '4kb'}; //
(function(_){console.log(_.libName,_.size)}(jqueryCloneLibrary))
Above, a clone on global level has been declared and stored as a reference in var jqueryCloneLibrary.
The reference to the object i.e jqueryCloneLibrary is passed as an argument to the IIFE (immediately invoked function)
Inside the function definition, we have the parameter defined as an _ using which we are able to access the properties _.name and _.size.
We include jquery or any other library the similar way and this is known as a Global Import.

JavaScript: global scope

Nowdays, i create a .js file with a lot of functions and then I link it to my html pages. That's working but I want to know what's the best way (good practices) to insert js in my pages and avoid conflicts with scope...
Thank you.
You could wrap them in an anonymous function like:
(function(){ /* */ })();
However, if you need to re-use all of the javascript functions you've written elsewhere (in other scripts), you're better off creating a single global object on which they can be accessed. Either like:
var mySingleGlobalObject={};
mySingleGlobalObject.someVariable='a string value';
mySingleGlobalObject.someMethod=function(par1, par2){ /* */ };
or the alternative, shorter syntax (which does the same thing):
var mySingleGlobalObject={
someVariable:'a string value',
someMethod:function(par1, par2){ /* */ }
};
This can then be accessed later from other scripts like:
mySingleGlobalObject.someMethod('jack', 'jill');
A simple idea is to use one object that represents your namespace:
var NameSpace = {
Person : function(name, age) {
}
};
var jim= new NameSpace.Person("Jim", 30);
The best way is to create a new scope and execute your code there.
(function(){
//code here
})();
This is best used when the global scope is accessed at a minimum.
Basically, this defines an anonymous function, gives it a new scope, and calls it.
It's perhaps not the BEST way, but a lot of PHP systems (I'm looking at you, Drupal) take the name of their particular plugin and prepend it to all their function names. You could do something similar, adding the name of your capability to your function names - "mything_do_action()"
Alternately, you could take a more "OO" approach, and create an object that encapsulates your capability, and add all your functions as member functions on IT. That way, there's only one thing in global scope to worry about.

Categories