What does !function ($) { $(function(){ }) }(window.jQuery) do?

Grishma U picture Grishma U · Jun 5, 2012 · Viewed 30.8k times · Source

I'm using twitter bootstrap to create a site and was trying to initialize tooltips. Apart from adding something like:

 $("[rel=tooltip]").tooltip()  
in application.js , unless I retain, the following piece of code used in bootstrap docs, my tooltips don't initialize.

!function ($) {

  $(function(){  

  })

}(window.jQuery)

What does the above code do?

Answer

Prasenjit Kumar Nag picture Prasenjit Kumar Nag · Jun 5, 2012

Lets explain by Breaking up the code

function () {
}()

Or often written as

(function () {
})()

Is a self-invoking anonymous function, also known as Immediately-Invoked Func­tion Expres­sions (IIFEs). Which executes the anonymous function inline immediately.

Read more about this at Explain the encapsulated anonymous function syntax.

Anonymous functions are a powerful feature and have benefits like scoping ("variable name spacing"), see What is the purpose of a self executing function in javascript?.


Now they are using

function ($) {

}(window.jQuery)

Let's skip the ! for now.

So they are passing, window.jQuery into that function as argument and accepting as $.

What this does is making $ an alias to window.jQuery (original jQuery Object) and hence ensuring that the $ will always refer to the jQuery object inside that closure, no matter if other library has taken that($) outside.

So code you write inside that closure using $ will always work.

Another benefit is that $ comes as an argument in the anonymous function, which brings it closer in the scope chain and hence it takes less time for the JS interpreter to find the $ object inside the closure than it would otherwise took if we used the global $.


$(function(){  

})

It's jQuery's document ready block as you might already know, which ensures that code inside this function will run when dom is ready, and hence all event binding's will work properly.

Read more at http://api.jquery.com/ready/

And what that ! does has been well explained here or at What does the exclamation mark do before the function?

In Short:

To demonstrate the benefits of !, Lets consider a case,

(function() {
    alert('first');
}())


(function() {
    alert('second');
}())

If you paste the above code in console, you will get two alerts, but then you will get this error

TypeError: undefined is not a function

Why this happens? Let's simulate how JS engines executes the above code block. It executes this anonymous function function() {alert('first');}() shows the alert and as it returns nothing undefined is returned inside the (). Same happens for the second function too. So after the execution of this block, it ends up having something like

(undefined)(undefined)

and as it's syntax is like a self-invoking anonymous function, it tries to call that function, but the first, (undefined) is not a function. So you get undefined is not a function error. ! fixes this kind or errors. What happens with !. I am quoting the lines from the above answer link.

When you use !, the function becomes the single operand of the unary (logical) NOT operator.

This forces the function to be evaluated as an expression, which allows it to be invoked immediately inline.

and this solves the above problem, we can rewrite the above block using ! like

!(function() {
    alert('first');
}())


!(function() {
    alert('second');
}())

For your case you can simply put your tooltip code inside a document ready block like this

$(function(){  
    $("[rel=tooltip]").tooltip();  
});

and it will work fine.

And if you just use $("[rel=tooltip]").tooltip() without any doc ready block, then there is a chance when this code will run, there isn't any element with rel=tooltip in DOM yet. So $("[rel=tooltip]") will return an empty set and tooltip won't work.

An example markup when it won't work without doc ready block,

.
.
.
<script type="text/javascript">
    $("[rel=tooltip]").tooltip();
</script>
.
.
.
.
<a href="#" rel="tooltip">Something</a>
<a href="#" rel="tooltip">Something</a>
<a href="#" rel="tooltip">Something</a>

As browsers, interprets the markup sequentially, it will execute the js code as soon as it face it as. And when it executes the JS block here, it hasn't yet parsed the a rel="tooltip" tags yet, as it appears after the JS block, So they are not in DOM at that moment.

So for the above case $("[rel=tooltip]") is empty and hence tooltip won't work. So it's always safe to put all your JS code inside document ready block like

$(function){
    // put all your JS code here
});

Hope all this makes sense to you now.