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 ) {
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.
Related
I have noticed a lot of libraries use this style below to define their library. I also notice that the first self invoking function has something to do with Require.js or AMD systems, they always have factory as an argument, I will look more into Require.js, always been into Browserify.
Why is the main code passed into the end of the first self invoking function inside parentheses, is this is a closure, or just considered an anonymous function, I will dig deeper into both. What are the benefits to this? It looks like inside the closure the author passes a string, this, and a callback.
Will this give my library a clean safe way to globalize the main object in this example below Please?
(function( globalName, root, factory ) {
if ( typeof define === 'function' && define.amd ) {
define( [], factory );
}
else if ( typeof exports === 'object' ) {
module.exports = factory();
}
else{
root[globalName] = factory();
}
}('Please', this, function(){
I am trying to dig really deep into JavaScript and create my own small MVC architecture, I don't want to hear I am silly or its been done before, I want to challenge myself and learn.
If there are any great resources for creating a JavaScript library or even better an MVC library I would love to know.
This code pattern is called Universal Module Definition (UMD). It allows you to make your JavaScript library usable in different environments. It provides three ways of defining modules:
Asynchronous Module Definition (AMD), implemented by RequireJS and Dojo Toolkit.
define( [], factory );
CommonJS — NodeJS modules.
module.exports = factory();
Assigning module to the global object, for example window in browsers.
root[globalName] = factory();
The IIFE has three parameters: globalName, root and factory.
globalName is the name of your module. It applies only to the third way of defining a module, i.e. assigning your module object to the global variable. For example, if you set this parameter to "myAwesomeModule" and use the code in browser (without AMD), you can access your module using myAwesomeModule variable.
root is the name of global object. Obviously, it also applies only to the third way of defining a module. Usually this is passed as this parameter, because this is a reference to window in browser. However, this doesn't work in strict mode. If you want your code to work in strict mode, you can replace this with typeof window !== "undefined" ? window : undefined.
Finally, factory is an anonymous function, which should return your module as object.
See also:
What is the (function() { } )() construct in JavaScript?
What Is AMD, CommonJS, and UMD?
This is an example of Universal Module Definition (UMD). It is a technique to make a JS module compatible with the three popular JS module specs:
Asynchronous Module Definition (AMD, used by Require.js)
define('name', [ /* dependencies */ ], factory);
CommonJS (Node.js ecosystem)
module.exports = object;
Global exports (for example, on window in the browser)
global['name'] = object;
UMD wraps a factory function responsible for creating the object to be exported and passes it as an argument to an immediately invoked function expression (IIFE), as in the snippet you pasted. The IIFE is responsible for detecting the module environment, and exporting the object created by the factory in an appropriate way. The pattern is as follows:
(function (name, root, factory) {
// detect the module environment and
// export the result of factory()
})('name', this, function () {
// module code
// return the object to be exported
});
Many transpilers and build tools generate this wrapper automatically.
I want to grab browser version and OS from useragent via js - this is a practicing example (cause yes - I know - feature detection is how you do it properly ;).
I stumbled across a little library that does so and now I'm trying to understand whats going on.
See this Codepen: http://codepen.io/anon/pen/gPWZGE?editors=001
obviously by running bowser.version - you get the version extracted from the browsers useragent. However the function bowser itself is an anonymous function - even though I can access elements within this function which has to do with this part of the code
!function (name, definition) {
var module;
var define;
if (typeof module != 'undefined' && module.exports) module.exports = definition();
else if (typeof define == 'function' && define.amd) define(definition);
else this[name] = definition();
}
To be honest I have hardly any idea whats going on there - can someone please explain what those lines are doing?
Thanks a lot
Ok, so step by step ...
first you have an IIFE
!function( name, definition ) {
// some code
}( 'bowser', function(){
// your module code
});
this calls the first function immediately with two parameters: the name of the module (here "bowser") and the actual definition function. In that definition function you create the module: You define any objects, properties and whatever else it needs to work. Important point is: You interface (the view the "outside" has on your module, has to be returned by that defintion function (in your codepen this is line 282: return bowser;).
The outer function then determines, how to publish your module:
First it looks for a CommonJS environment:
typeof module != 'undefined' && module.exports
This would be used, e.g., inside NodeJS. If it found the respective objects, it will export your module as a CommonJS module: module.exports = definition().
If this was not a CommonJS environment, the script looks, if it is an AMD (for example, requireJS):
typeof define == 'function' && define.amd
Again, if that matches, the module is exported as a AMD module: define(definition).
Finally, if this is neither CommonJS nor AMD, the script assumes it is a (vanilla) browser or something similar and just attaches the module to the global namespace:
this[name] = definition();
Note, that each time the definition function is called and the return value is exported as a module. This is why your definition function has to return the module interface.
I was browsing through the source code here: http://js-dos.com/games/doom2.exe.html and noticed a few things:
if (typeof Module === 'undefined')
{
Module = eval('(function() {try { return Module || {} } catch(e) { return {} }})()');
}
The Module function is defined with an inline script tag
It is later declared again with var in another inline tag, this time it checks if the Module exists.
My question: What is the point of declaring Module with a self invoking function if it'll only try to return the Module again? Hasn't it already been proven that it doesn't exist? Why not just explicitly declare Module as {}?
typeof Module might be undefined if Module is a local variable that happens to contain undefined. This code is meant to support a few cases, Module might be local or global, and defined or undefined. We want to avoid polluting the global scope, so we don't just do Module = ... if it's undefined.
First, the usual case is emscripten-generated code in the global scope. In this case, Module may or may not be defined, and may be local but still undefined, so we need to handle both.
Second, emscripten code may be just a module, like a game that uses ammo.js. In that case, the usage is
function Ammo(Module) {
// emscripten-generated code, uses the Module
return something;
}
so Module in this case is a function local, given as a param already defined for us.
We can't just declare var Module because that means Module is a local variable. So we need eval. For eval, we need a function that returns a value, because we need a try-catch. The try-catch uses Module, and will throw if Module is not a local (regardless of whether it contains undefined or not), which is exactly what we want.
It's possible this code could be simplified, though!
Sorry if this type of question asked many times before but I'm little unclear with the jQuery coding here:
From http://code.jquery.com/jquery-latest.js
(function(global,factory){
//some checks and coding
})(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
//coding stuff
})
So, the jQuery is using the coding in that closure but how the jQuery is available outside that scope?
In the very end of this IEFE closure you can see the lines
// 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;
}
where they export the $ and jQuery identifiers to the global window object. This function with the // coding stuff itself is the second argument of the IEFE that you posted, and will - as the factory be called appropriately depending on what module loaders are available (or not).
Inside of the closure you can find this line of code:
return (window.jQuery = window.$ = jQuery);
So jQuery constructor function is explicetly assigned to window.jQuery. That's why it's available outside.
Looking at the code of ryanve's response.js, it begins with the following:
(function(root, name, make) {
var $ = root['jQuery'] || root['Zepto'] || root['ender'] || root['elo'];
if (typeof module != 'undefined' && module['exports']) module['exports'] = make($);
else root[name] = make($);
}(this, 'Response', function($) {
...
What is this called, why is it useful and what does it do exactly?
This:
(function(root, name, make){...})(this,'Response', function($){...});
calls "init" function passing default namespace (this is window in browsers) reference as the root variable.
This:
var $ = root['jQuery'] || root['Zepto'] || root['ender'] || root['elo'];
gets reference of either jQuery or Zepto, etc. ... module.
And this:
if (typeof module != 'undefined' && module['exports'])
module['exports'] = make($);
else
root[name] = make($);
checks if file is loaded with module object (most probably CommonJS environment) available and calls "constructor" make() and registers its exhaust as a module.
Otherwise registers make() result as an object in global namespace ( root[name] = ... )
This is kind of hook. This is exactly you can add current plugin name "Response" with any of mentioned library like "jQuery, Zepto, ender, elo". And again "Response" leave anchor point
in following code.
if (typeof module != 'undefined' && module['exports']) module['exports'] = make($);
else root[name] = make($);
And code it self need some changes. Let us take jQuery, here "this" refers window, based on the code the author trying to like window.jQuery.Response = function(jQuery){} and module in "if" condition is a global. It will be available when you are working NodeJs like environment. In this case, Response attached with that global variable, instead of jQuery.
Note: Simply we can say, "Response" definition can work with any of mention library and/or library which expose "module" global.
This pattern helps avoid writing code in the global scope, and the function written on the first line of your code is a self invoking function. A self invoking function is invoked as soon as it is declared. Here is how to do it.
(function(argument1, argument2, argument2){
alert("Self invoked");
})(arg1, arg2, arg3);
in your case the first argument is this which refers to the window object, second is a string and third is a callback.