Last Updated: February 25, 2016
·
3.77K
· fedemp

Pass the jQuery and other global objects to anonymous functions in CoffeeScript

Usually you may see this way of calling an anonymous function.

(function($) {
    //Your code here.
})(jQuery);

From http://stackoverflow.com/questions/10371539/why-define-anonymous-function-and-pass-it-jquery-as-the-argument you can learn:

The purpose of this code is to provide "modularity", privacy and encapsulation for your code. The implementation of this is a function that is immediately invoked by the calling (jQuery) parenthesis. The purpose of passing jQuery in to the parenthesis is to provide local scoping to the global variable. This helps reduce the amount of overhead of looking up the $ variable, and allows better compression / optimization for minifiers in some cases.

To achieve the same output using coffeescript you use:

(($) ->
    $('body').addClass('foo')
)(jQuery)

or

do (jQuery) ->
    $ = jQuery
    $('body').addClass('foo')

Note the difference between the two. The first takes advantage of the fact that CoffeeScript is just Javascript and is very similar to the original JS function. The second one, easier to read, requires an extra line cause the name of the variable the anomynous function receives is the same as the variable sent on execution i.e. we create a variable named "jQuery" to receive an argument and CoffeeScript compiles this to pass the variable jQuery from the outer scope.

So, these two code snippets compile to:

(function($) {
    return $('body').addClass('foo');
})(jQuery);

and

(function(jQuery) {
    var $;
    $ = jQuery;
    return $('body').addClass('foo');
})(jQuery);

Problem arises when you try to minify these two blocks using uglifyjs. The first results in:

(function(e){return e("body").addClass("foo")})(jQuery)

but the second in:

(function(e){var t;return t=e,t("body").addClass("foo")})(jQuery);

which is actually larger. This has been reported; let's see what happens next: https://github.com/mishoo/UglifyJS2/issues/27

Back to the beggining. What if you want the window and window.document objects.

The first one is really easy and will compile just as good as the jQuery example:

((window, document) ->
  // Your code here
)(window, window.document)

For the second option we can't expect to receive window.document cause variable can't contain periods in its name

// This is not valid
do (window, window.document) ->
  // Your code here

// This is valid
do (window) ->
  document = window.document
  // Your code here

By the way, both (valid examples) compiled JS are minified the same way.

1 Response
Add your response

You could do this:

do ($ = jQuery) ->
# stuff here

over 1 year ago ·