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.
Related
So I tried to include threejs as a drop-in script into my code. No webpack, no browserify, no requirejs. Just a simple gulp/browsersync serve.
I load an external angular app and extend it. Now I need my own THREEjs Version within the codebase.
It gets loaded - but right in the first line they try to set the variable 'global' which doesn't seem to be defined. What am I missing?
// edit:
I am using a js api from another company. I don't know if they set the 'global' var, but Threejs definitely tries to use the var 'global' although I don't use it in a node setup. but in all examples it just works as a drop-in script.
If I use the minified version the error changes to
TypeError: global is undefined
*three.min.js:2:168
anonymous
https://localhost:9000/scripts/three.min.js:2:168
anonymous
https://localhost:9000/scripts/three.min.js:2:2*
and this originates from the following first lines of the three.js file:
function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.THREE = {}))); }(this, (function (exports) { 'use strict'; ...
//EDIT 2:
I finally maaged to find the error which is causing all this.
if youre using gulp-babel and include scripts with that snippet on top, babel tries to replace THIS with the current context, which is - of course - undefined. and thats why bable literally replaces this with undefined. so: never babel() your final vendor files!
The part of THREE.js that you show in your question is not a problem. If we focus only on the problem you've been having, and eliminate the code for the CommonJS and AMD cases, it boils down to this:
(function (global, factory) {
factory(global.THREE = {});
}(this, (function (exports) { 'use strict';
// ...
})));
This is a common pattern. Note that the first anonymous function is called with this as the first argument. So global is set to the value that this has in the global space. If the code above executes in a top-level execution context, then this will automatically have the value of the global object for the environment in which you run the code. In Node, that object is named global. So open a Node session and type:
global === this
You'll get true. In a browser the global object is named window. Open the console in debugging and type:
window === this
You'll get true. So what the code snippet with the anonymous function does is that it uses this to grab a reference to the global object irrespective of where the code executes. It does not have to check whether window exits or global exist, or self or anything else. Instead, it just passes this to the anonymous function and, this way, automatically gets a reference to the global object. There's nothing wrong with that method. It is super common and generally works.
However, it is possible to prevent the code from working properly. For instance if the code above is wrapped in another function and that function uses "use strict", then this will be undefined, and global will be undefined too. Here's an example:
(function() {
"use strict";
(function(global, factory) {
console.log("XXX", global); // You'll get "XXX undefined" here
}(this, (function(exports) {
'use strict';
})));
}());
Sometimes, build processes or code loading tools add such wrapping code, and then they mess up the original code.
Since "just getting babel to ignore certain files" is by no means trivial when working in gulp, a quick and dirty fix for this error is to swap this with window on the 5th line of three.js:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.THREE = {})));
}(window, (function (exports) { 'use strict';
Is this what you need? Just add this one-liner at the very head of your code, in the global scope:
if (typeof global === "undefined"){global=window;}
This is going to reference the global object to the window object, which is the object containing all global variables in browser.
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 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.
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.
I am so confused about JavaScript's object system. I know that everything is considered Object in JavaScript but in this code of Esprima, I don't see any statement to declare this project to be accessed with esrpima like the following line: (https://github.com/ariya/esprima/blob/master/esprima.js)
var syntax = esprima.parse(text);
My question is how and where to define something like esprima.parse(text) in Javascript so that it can be exported as external package and be accessed with the object name. I know how to define object like Object = {a: "B"}; but can't find a way to figure this out. Please help me!
(function (root, factory) {
'use strict';
// Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
// Rhino, and plain browser loading.
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((root.esprima = {}));
}
}(this, function (exports) {
'use strict';
var Token,
TokenName,
...
That's because it doesn't. The variable name, esprima, comes from code that includes esprima. For example:
var esprima = require('esprima');
esprima.parse(text);
You could give the variable any other name:
var foo = require('esprima');
foo.parse(text);
All the the esprima.js file does is define an object which is exported. It does not dictate the name of the variable to which the object is assigned to eventually.
If the script is loaded in a browser, it actually does define esprima explicitly. You can see it in line 55:
factory((root.esprima = {}));
This creates an object and assigns it to root.esprima. But it's also a function call, so the object is passed to factory, which is the function defined in 57, which accept a parameter exports. This is where the code assigns all the properties to.