2

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.

Community
  • 1
  • 1
blindsnowmobile
  • 3,868
  • 6
  • 32
  • 47

4 Answers4

5

Simple explanation

It just creates a closure where you can reference jQuery with $, 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 passing jQuery as the only argument, so $ serves as an alias to jQuery inside 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:

jQuery.noConflict();
(function($) { 
  $(function() {
    // more code using $ as alias to jQuery
  });
})(jQuery);

That closure aliases jQuery as $ 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 $ with jQuery, 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. :)

Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
4

I'll do my best to answer these questions. I'm on an iPad so bear with me if I'm I leave out some technical details. These points are a little simplified, but they help describe what's goin on :)

  • $ is being passed in because $ could of been overridden to mean something else. jQuery could also be in noCinflict mode.
  • What (jQuery) is doing is calling, immediately, the inline function that's defined. This is known as a self-executing function. While not correct (it doesn't execute itself, we do that), thats what its been come to be known as. It passes jQuery to the function so we have a value for $. As mentionEd in another answer, this creats a closure. I'd suggest googling "JavaScript closures". You'll find some very valuable information :)

Hope that helps :)

Jason L.
  • 2,464
  • 1
  • 23
  • 41
3

This will answer your questions: http://docs.jquery.com/Plugins/Authoring

Sang Suantak
  • 5,213
  • 1
  • 27
  • 46
3

What you are looking is extending jQuery with new plugins "the part you are extending $.fn". and it is wrapped in a closure block.

(function($){
//do sth
})(jQuery);

The above code is the part you must consider. To describe it see below example:

1. declare a function and calling it

var fn = function(b){ /*do sth like alert(b)*/ };
fn('hiiii');

2. shorter syntax is

(function(b){ /*do sth like alert(b)*/ })('hiiii');

Now if you replace b with $ and passed parameter 'hiiii' with jQuery you end up with:

(function($){ /*do sth with $*/ })(jQuery);

As you see in first example b is methods parameter and 'hiiii' is passed parameter at call time. Same for what you have above, $ is methods parameter and jQuery is the passed parameter at call time.

The reason is to avoid conflicts with other libraries as $ has been used widely in almost all JS libraries. So you can use jQuery along other libraries.

And if you want to read more about how to develop plugins go to this post

James
  • 79
  • 3