310

I am just starting out with writing jQuery plugins. I wrote three small plugins but I have been simply copying the line into all my plugins without actually knowing what it means. Can someone tell me a little more about these? Perhaps an explanation will come in handy someday when writing a framework :)

What does this do? (I know it extends jQuery somehow but is there anything else interesting to know about this)

(function($) {

})(jQuery);

What is the difference between the following two ways of writing a plugin:

Type 1:

(function($) {
    $.fn.jPluginName = {

        },

        $.fn.jPluginName.defaults = {

        }
})(jQuery);

Type 2:

(function($) {
    $.jPluginName = {

        }
})(jQuery);

Type 3:

(function($){

    //Attach this new method to jQuery
    $.fn.extend({ 

        var defaults = {  
        }  

        var options =  $.extend(defaults, options);  

        //This is where you write your plugin's name
        pluginname: function() {

            //Iterate over the current set of matched elements
            return this.each(function() {

                //code to be inserted here

            });
        }
    }); 
})(jQuery);

I could be way off here and maybe all mean the same thing. I am confused. In some cases, this doesn't seem to be working in a plugin that I was writing using Type 1. So far, Type 3 seems the most elegant to me but I'd like to know about the others as well.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
Legend
  • 104,480
  • 109
  • 255
  • 385
  • 23
    It's bed time here, but just for starters, `(function($) { })(jQuery);` wraps the code so that `$` is `jQuery` inside that closure, even if `$` means something else outside of it, usually as the result of [`$.noConflict()`](http://api.jquery.com/jQuery.noConflict/) for example. This ensures your plugin works, whether or not `$ === jQuery` :) – Nick Craver May 30 '10 at 01:51
  • 4
    About `(function($) { })(jQuery)` you said : "I know it extends jQuery somehow [...]". Clearly you do *not* know since your statement is 100% false. By the way it can be misleading for future readers. Take a look at this : http://stackoverflow.com/a/32550649/1636522. – leaf Mar 03 '17 at 06:35
  • Extending on @NickCraver's comments, jquery-ui-1.7.2.custom.min.js uses this for example: jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla........})(jQuery);. I know that is an old version of jQuery UI with deprecated code, but the point is to show how in that case, they are using "c" instead of "$". – Jaime Montoya Sep 18 '17 at 23:44

6 Answers6

244

Firstly, a code block that looks like (function(){})() is merely a function that is executed in place. Let's break it down a little.

1. (
2.    function(){}
3. )
4. ()

Line 2 is a plain function, wrapped in parenthesis to tell the runtime to return the function to the parent scope, once it's returned the function is executed using line 4, maybe reading through these steps will help

1. function(){ .. }
2. (1)
3. 2()

You can see that 1 is the declaration, 2 is returning the function and 3 is just executing the function.

An example of how it would be used.

(function(doc){

   doc.location = '/';

})(document);//This is passed into the function above

As for the other questions about the plugins:

Type 1: This is not a actually a plugin, it's an object passed as a function, as plugins tend to be functions.

Type 2: This is again not a plugin as it does not extend the $.fn object. It's just an extenstion of the jQuery core, although the outcome is the same. This is if you want to add traversing functions such as toArray and so on.

Type 3: This is the best method to add a plugin, the extended prototype of jQuery takes an object holding your plugin name and function and adds it to the plugin library for you.

cda01
  • 1,265
  • 3
  • 13
  • 25
RobertPitt
  • 54,473
  • 20
  • 110
  • 156
  • 2
    if you read the original question, the OP specifies 3 methods of writing closures, he named those methods type {1,2,3}, I am mealy referring to the areas within the question with an answer.. – RobertPitt Apr 04 '14 at 12:02
  • 1
    ( function(){} ) means returns the inside function ? What exactly the "()" means? – JaskeyLam Feb 02 '15 at 05:37
  • I like the first example bu the second one using line number references (which is not a js feature) is unclear. – Samy Bencherif May 16 '16 at 17:55
  • 1
    That's called Immediately Invoked Function Expression (IIFE): http://benalman.com/news/2010/11/immediately-invoked-function-expression/ – Andres Rojas Aug 29 '16 at 16:04
  • 1
    I have most problems understanding the outer parenthesis of`( function(){} )`: What is this exactly? Can I not just write `function(){}()`? – TMOTTM Aug 17 '17 at 18:46
129

At the most basic level, something of the form (function(){...})() is a function literal that is executed immediately. What this means is that you have defined a function and you are calling it immediately.

This form is useful for information hiding and encapsulation since anything you define inside that function remains local to that function and inaccessible from the outside world (unless you specifically expose it - usually via a returned object literal).

A variation of this basic form is what you see in jQuery plugins (or in this module pattern in general). Hence:

(function($) {
  ...
})(jQuery);

Which means you're passing in a reference to the actual jQuery object, but it's known as $ within the scope of the function literal.

Type 1 isn't really a plugin. You're simply assigning an object literal to jQuery.fn. Typically you assign a function to jQuery.fn as plugins are usually just functions.

Type 2 is similar to Type 1; you aren't really creating a plugin here. You're simply adding an object literal to jQuery.fn.

Type 3 is a plugin, but it's not the best or easiest way to create one.

To understand more about this, take a look at this similar question and answer. Also, this page goes into some detail about authoring plugins.

Community
  • 1
  • 1
Vivin Paliath
  • 87,975
  • 37
  • 202
  • 284
  • 1
    I'm unsure how Type 3 is extending the core. Its a perfectly valid way to create a plugin since you're extending the prototype. Albeit a bit unnecessary. – tbranyen May 30 '10 at 15:32
  • 1
    My bad - I should have been more clear. I was in a hurry and you are correct. – Vivin Paliath May 31 '10 at 16:42
36

A little help:

// an anonymous function
  
(function () { console.log('allo') });

// a self invoked anonymous function

(function () { console.log('allo') })();
  
// a self invoked anonymous function with a parameter called "$"
  
var jQuery = 'I\'m not jQuery.';

(function ($) { console.log($) })(jQuery);
leaf
  • 14,210
  • 8
  • 49
  • 79
23

Just small addition to explanation

This structure (function() {})(); is called IIFE (Immediately Invoked Function Expression), it will be executed immediately, when the interpreter will reach this line. So when you're writing these rows:

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

this means, that the interpreter will invoke the function immediately, and will pass jQuery as a parameter, which will be used inside the function as $.

Commercial Suicide
  • 13,616
  • 13
  • 48
  • 72
16

Actually, this example helped me to understand what does (function($) {})(jQuery); mean.

Consider this:

// Clousure declaration (aka anonymous function)
var f = function(x) { return x*x; };
// And use of it
console.log( f(2) ); // Gives: 4

// An inline version (immediately invoked)
console.log( (function(x) { return x*x; })(2) ); // Gives: 4

And now consider this:

  • jQuery is a variable holding jQuery object.
  • $ is a variable name like any other (a, $b, a$b etc.) and it doesn't have any special meaning like in PHP.

Knowing that we can take another look at our example:

var $f = function($) { return $*$; };
var jQuery = 2;
console.log( $f(jQuery) ); // Gives: 4

// An inline version (immediately invoked)
console.log( (function($) { return $*$; })(jQuery) ); // Gives: 4
Krzysztof Przygoda
  • 1,045
  • 1
  • 12
  • 23
11

Type 3, in order to work would have to look like this:

(function($){
    //Attach this new method to jQuery
    $.fn.extend({     
        //This is where you write your plugin's name
        'pluginname': function(_options) {
            // Put defaults inline, no need for another variable...
            var options =  $.extend({
                'defaults': "go here..."
            }, _options);

            //Iterate over the current set of matched elements
            return this.each(function() {

                //code to be inserted here

            });
        }
    }); 
})(jQuery);

I am unsure why someone would use extend over just directly setting the property in the jQuery prototype, it is doing the same exact thing only in more operations and more clutter.

tbranyen
  • 8,008
  • 1
  • 19
  • 18