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:
function(w)
at module.exports
?noGlobal
variable?factory
actually set up and what is its type?factory
argument get called with one argument and with two as well?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 ) {
What is the use of the recursive call to
function(w)
atmodule.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.
// 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.