Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript UMD - where/how are root, factory defined?

Tags:

javascript

umd

In a simple UMD setup like the following, where/how are root and factory defined?

(function (root, factory) {

    // environment detection here
    console.log(root);
    console.log(factory);

}(this, function (b) {

    // module definition here

}));

I'm arriving late to the UMD party, so please forgive me if this is a silly question... but if I run the above code, I see root returns the window object, and factory returns a function. So is the first argument (in this case, root) always defined as the window object? What about the second? Are they implemented the same cross browsers? I'm searching high and low for a spec or reference to back this up and can't find one... there are lots of blog posts about the wonders of UMD, but I can't find any explanation of how this magically works.

Does anybody have a simple explanation for how or why this works?

like image 589
David R. Avatar asked Dec 09 '22 01:12

David R.


1 Answers

This is an IIFE (immediately-invoked function expression), which is nicely explained here.

To put it simply you are creating a function that is only called once and you are passing to it two arguments, this and function(b). These two arguments are named root and factory inside the IIFE body.

The benefit is that the body of IIFE works in isolation, in a "private scope". Variable names outside of it have no effect and you have no conflict problems.

Now, back to your question, you are passing this as an argument. This is the global object. In a browser it is window and in Node it is global. In both cases in the IIFE you are referring to it as root and in your module as b. What ever you call it, another advantage is that your minifier can pick it up and translate it to c or something else without breaking your code. This is in contrast with a normal situation, where window or document or any module names can't be minified.

You are also passing a function, which is named factory. This is your module. Without AMD or CommonJS, you would usually do:

(function (root, factory) {
    root.myModuleName = factory(root);  
}(this, function (b) {
    // module definition here
}));

This will create your module and attach it to the global object, so that you can use it. With only one argument in factory method, you normally need to pass the global object. You can also use more arguments to pass any module dependencies:

(function (root, c, factory) {
    root.myModuleName = factory(root, c);  
}(this, jQuery, function (b, $) {
    // module definition here
    // You refer to jQuery as $ without having to call noConflict
}));
like image 131
kgiannakakis Avatar answered Dec 11 '22 10:12

kgiannakakis