I need help understanding this pattern for jQuery plugin authoring. Can somebody explain this simple bit of code for me?
(function($) { /* Code here */ })(jQ
What you have there is shorthand for something like this:
function anonymous_function($) {
// Code here
};
anonymous_function(jQuery);
As you can see, it allows the $
symbol to be used as a reference to the jQuery
object inside the function.
A function in JavaScript can be either a statement or an expression. When you use a function expression, you can pass it around like any other value:
> console.log(function() { 1 + 1; });
> (function() {}) && doExpensiveWork();
// etc.
One of the things you can do with a function expression is immediately invoke it. In such cases the function is called an immediately invoked function expression (or IIFE for short):
> (function() { console.log("IIFE running"); })();
IIFE running
This is the same as creating the function and invoking it in two steps:
> var notAnIIFE = function() { console.log("running"); };
> notAnIIFE();
running
A function expression can, of course, take arguments:
> var someFunction = function(x, y) { return x + y; };
> var seven = someFunction(3, 4);
> seven
7
So an IIFE can be invoked with arguments as well:
> var seven = (function(x, y) { return x + y; })(3, 4);
> seven
7
In the case of an invocation like this:
(function($) { /* do work with $ */ })(jQuery);
the value bound to the name jQuery
is being passed into the function expression as the argument $
. This is similar to doing the following:
var initializePlugin = function($) {
/* do work with $ */
};
initializePlugin(jQuery);
but it leaves no trace in the parent namespace (whereas, in our second example, our initializePlugin
name is left behind after we finish setting up our plugin).
The function in javascript creates a scope, it's not just about the $
variable, but about variables local to the function. And given the $
parameter, it becomes local to the function and safe to use, referring to jQuery
.
+1 for jfriend00's answer.
But including jQuery in a page overwrites both of the global symbols jQuery and $ (see jQuery.js line 9579) potentially causing conflicts with other libraries that define a global $.
So taking this a step further to also stop the global $ conflict:
(function($) {
// you can use $ here to refer to jQuery
})(jQuery.noConflict());
as demonstrated by:
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script>
(function($) {
console.log('want $ to be jQuery here so want true: ' + ($ === jQuery));
})(jQuery.noConflict());
console.log('do not want $ to be jQuery here so want false: ' + ($ === jQuery));
</script>
Let's break this down:
(function($) { /* Code here */ })(jQuery);
First, the construct:
(function() {})();
creates an immediately executed function expression (often called IIFE). This is a function that is executed immediately rather than defined now, but called later. It is essentially an anonymous (unnamed) function that is defined and then executed right away.
Then, passing jQuery to it like this:
(function() {})(jQuery);
passes jQuery as the first argument to that immediately executed function. Then, naming that first argument as $
defines that symbol inside the function to correspond to the first argument that is passed.
(function($) {})(jQuery);
which in expanded form looks like this:
(function($) {
// you can use $ here to refer to jQuery
})(jQuery);
There a couple nice thing about this for jQuery plugin authors:
The IIFE creates a local function context so you can have variables which are "global" for your plug-in, but are not actually global variables and thus don't pollute or conflict with the actual global variable namespace.
You can program with $
for jQuery, whether or not the host program actually has that defined for jQuery because you've defined $
locally within your function.