11

I understand how to define functions like this:

function myfunc(x,y,z) {
   alert("Just an example " + x + y + z)
}

But not this:

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

    <script>
        (function ($) {
        $.fn.idle = function (x, y, z) {
            alert("Just an example " + x + y + z)
    }(jQuery));
    </script>

The above is a part of a library I'm using, but I simply can't understand the $.fn.idle bit.

What is it doing? It's defining a function called 'idle', somehow, but what about the $.fn? And what about the (function ($) { part? Again, I understand $(document).ready(function() { but (function ($) { is completely alien. Is it a short hand?

And what is the significance of the (jQuery)); at the bottom?

m90
  • 11,434
  • 13
  • 62
  • 112
Starkers
  • 10,273
  • 21
  • 95
  • 158

4 Answers4

8

An immediately invoked function expression which aliases jQuery to $ inside its scope:

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

It creates and executes a function immediately. This way you can use $ inside the function to reference jQuery regardless of what the global $ references to. Useful for pages using jQuery.noConflict(). Also the variables declared inside that IIFE don't leak to the global scope.


As for the other part of the question, $.fn === jQuery.prototype. So by adding a method to the jQuery prototype, you may call it on any jQuery object. E.g.:

$.fn.doSomething = function(){}; //add a method to the jQuery prototype
$('selector').doSomething(); //then you may call it on any jQuery object

More on jQuery plugin authoring.

Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
  • Why do they reference the prototype instead of making us use it ? – Virus721 Jul 30 '13 at 15:19
  • Oh just noticed that my websockets are broken on Nightly. @Virus721 Sorry not sure what you meant. `jQuery.fn` is just a shortcut (reference) to `jQuery.prototype`, "Write less, do more" as they say. You may use either of these. `=]` – Fabrício Matté Jul 30 '13 at 15:24
  • @Virus721 because fn is 7 characters shorter than prototype? i don't know. – Kevin B Jul 30 '13 at 15:26
  • Other libraries such as Moment.js also use `fn` as shortcut for `prototype`, too. – Fabrício Matté Jul 30 '13 at 15:27
  • 1
    I imagine making such a shortcut can cut down on the minified size of the library and it's plugins quite a bit with how often it's used. – Kevin B Jul 30 '13 at 15:27
  • Before reading your answer i was thinking that fn was an object that was iterated over using for(var in) to copy every method from it into the newly created jQuery object, but i thought it was done manually, i havn't thought about it being the prototype. – Virus721 Jul 30 '13 at 15:29
  • Though most of the jQuery methods are defined like `$.fn = $.prototype = {/*methods*/}` ([source](https://github.com/jquery/jquery/blob/302f222df03d2c65f409b11b7fa65dba5400180f/src/core.js#L76)) or `$.fn.extend({/*methods*/})`, I agree that it should cut down some bytes as @KevinB said. `=]` – Fabrício Matté Jul 30 '13 at 15:29
1

This is known as an IIFE - Immediately Invoked Function Expression.

(function ($) {
    // inside stuff
}(jQuery));  

jQuery is imported to the function body as $, and the function is run immediately.

// inside stuff

$.fn.idle = function (x, y, z) {
    alert("Just an example " + x + y + z)
} // added in missing parentheses

$.fn is equivalent to jQuery.fn and jQuery.fn.idle is simply a property on jQuery.fn that points to a function.

Another interesting point, is that jQuery.fn is an alias for jQuery.prototype, i.e. they are the same thing.

A lot of aliases here makes the code a bit more complicated than it actually is.

This is a common structure you will see for adding plugins/mixins to a library.

Hope, I cut this up for you well.

nativist.bill.cutting
  • 1,292
  • 3
  • 11
  • 19
1

Adding functions to $.fn makes them available for use on jQuery objects.

$.fn.alertTitle = function() { alert( $(this).attr('title') ); };
$('#foo').alertTitle();
Virus721
  • 8,061
  • 12
  • 67
  • 123
1

this is assigning a function to a variable:

var test = function () { alert('testing'); }
test(); // will alert testing

A function assigned to a variable is also called an 'anonymous function' because it does not have a name, is is often used to pass a function as a parameter to another function.

In javascript, a variable may start with a $, and this is used by jQuery. jQuery is an object, which has properties, one of which is called fn. this property can also have properties, in this case idle.

so $.fn.idle = function () {}; comes down to this:

$ = {
    fn: {
        idle: function () {}
    }
};

This is also referred to as 'namespacing' although that can have other nuances aswell. Also be aware that the you can only assign properties to existing objects:

var myVar = {};
myVar.test.foo = {}; // results in error because myVar.test is undefined
myVar.test = {
    foo: {}
}; // this is correct
NDM
  • 6,731
  • 3
  • 39
  • 52