JQuery library module export
Asked Answered
F

1

10

I am trying to understand how jQuery sets itself up.

Right at the beginning jQuery automatically calls a function, which exports a module.

How does the setup work?

Here some more detailed sub-questions which might answer the the more general question:

  • What is the use of the recursive call to function(w) at module.exports?
  • What is the use of the noGlobal variable?
  • Where is the factory actually set up and what is its type?
  • Why can the factory argument get called with one argument and with two as well?
  • What is the global argument supposed to contain? (I wish there were a type like in c++...)

(function( global, factory ) {

    if ( typeof module === "object" && typeof module.exports === "object" ) {
        // For CommonJS and CommonJS-like environments where a proper `window`
        // is present, execute the factory and get jQuery.
        // For environments that do not have a `window` with a `document`
        // (such as Node.js), expose a factory as module.exports.
        // This accentuates the need for the creation of a real `window`.
        // e.g. var jQuery = require("jquery")(window);
        // See ticket #14549 for more info.
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }

    // Pass this if window is not defined yet
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
Fant answered 6/5, 2015 at 14:59 Comment(0)
B
19

What is the use of the recursive call to function(w) at module.exports?

It isn't a recursive call, more of a deferred initialization function. In some CommonJS environments, like Node.JS, the global object does not have a document property, while others such as Browserify and Webpack do.

jQuery requires the document property to initialize, so it first check to see if the global object contains a document property. If it does, it initializes immediately, making in-browser CommonJS environments happy. If it does not, it returns a function that can be used to later initialize jQuery. This function could later be called on a fake window, creating with something like jsdom.


What is the use of the noGlobal variable?

The noGlobal variable is used here.

Excerpt from jQuery:

// Expose jQuery and $ identifiers, even in
// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( typeof noGlobal === strundefined ) {
    window.jQuery = window.$ = jQuery;
}

Essentially, if noGlobal is undefined, jQuery will add itself to the global window object. The only time it will not do this is if it is loaded by a CommonJS loader, with a document property on the global object, such as Browserify or Webpack. The call below is where noGlobal is not undefined.

factory( global, true )

Where is the factory actually set up and what is its type?

The factory variable is a function, and it is declared here:

function( window, noGlobal ) {

It is the second argument passed into the IIFE.


Why can the factory argument get called with one argument and with two as well?

Because JavaScript.

In JavaScript, there is no requirement to match the number of arguments a function is declared with. Any omitted arguments have the value undefined.


What is the global argument supposed to contain? (I wish there were a type like in c++...)

It is supposed to contain the global object for the JavaScript environment. In a browser, this object is known as window, and in Node, this object is known as global. In both environments, using this in the global scope will resolve to the global object, whatever it's global name is.

However, due to some 3rd-party wrappers which can change the scope in which jQuery is initialized, jQuery will first check if the window object is available and use it if it is. If not use, it will default to using this.

typeof window !== "undefined" ? window : this

one more question: where is the w argument coming from?

When the global object does not contain a document, it returns a function that accepts one argument, the w. This object would be a window-like object with a document that can be created with something like jsdom.

Brass answered 11/5, 2015 at 3:44 Comment(6)
one more question: where is the w argument coming from?Fant
@Fant When the global object does not contain a document, it returns a function that accepts one argument, the w. This object would be a window-like object with a document that can be created with something like jsdom.Psalm
Does this mean w is a global variable which is available in the case that no document is available?Fant
Not exactly. When jQuery does not have global document, it will instead return a function which can later be used to init jQuery. To do that, you would call that function, and pass in the window-like object you want to initialize it on. The window-like object is something you would have to create, with something like jsdom and pass when you want to initialize it. Something like this: var $ = require('jquery')(myFakeWindow);, where myFakeWindow is the window-like object you created.Psalm
Ok, I got it: w is an argument to a function defined exactly at this location. It is a free variable which does not need to be defined at this point, right?Fant
@Fant It's technically an argument, not a free variable, but yes, jQuery does not define it. You would pass it in when you want to use it.Psalm

© 2022 - 2024 — McMap. All rights reserved.