I’m learning jQuery, and am attempting to understand the following code structure.
if(jQuery) (function($){
$.extend($.fn, {
MyPlugin: function(a, b) {
....
}
});
})(jQuery);
From what I can tell, this first checks to see if the jQuery object exists. If it does, it defines an inline function, which extends the jQuery object using the ‘fn’ attribute.
I’ve seen this question asked in a couple other places, for example here, but the points I’m not understanding haven’t been addressed. Where I’m getting confused…
-why is the special jquery “$” object passed to the initial function?
-why is the inline function passed the jQuery object (on the last line)? ie: (function($) {…})(jQuery);
Thanks.
Simple explanation
It just creates a closure where you can reference
jQuerywith$, even if it’s in noConflict mode.Also explained in jSang’s answer (+1)’s plugin authoring.
Technically, it just defines an Anonymous function which takes one argument called
$and immediately calls it passingjQueryas the only argument, so$serves as an alias tojQueryinside this function’s scope – note that the$in the global scope is not accessible inside this closure then.It means, if you had Prototype using
$in the global scope, you wouldn’t be able to access Prototype using$inside the closure, as the local scope$which references jQuery takes precedence.Of course, if you need another library’s methods inside your closure, you can define it using 2 arguments:
(function($j, $p) {and call it passing(jQuery, $)assuming another library is using the$namespace. Or more simply, alias your closure’s local scope var to something differently than your other library’s global scope var:(function($j) {, which means the global$will still be accessible inside the function’s scope. Note that this latter effect may be undesirable as you can’t be completely sure of what your user has assigned for$unless you explicitly write it in your documentation. I guess plugins which require multiple libraries are a little off-topic so let’s leave it at that.Slightly more detailed
A practical closure example from the noConflict docs page:
That closure aliases
jQueryas$inside its scope, very useful in case your user has Prototype or another library using the$global namespace, for instance. This makes your plugin much more sturdy and less error-prone.The closure can be used whether jQuery has control of the $ variable or not, hence it’s ideal for plugin authoring.
Imagine if one of your end-users had jQuery in noConflict mode and Prototype using the
$namespace, and your plugin tried to extend$with jQuery methods? The Chaos and Ponies!Of course, you could skip the closure and replace all
$withjQuery, but it’d make your code longer and less readable to many developers.Also, How do JavaScript closures work? has many useful answers if you have trouble understanding closures, even though this question shouldn’t require too much in-depth knowledge about closures.
:)