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.
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've been following this tutoral, and when referencing Module as an argument in ModuleTwo, everything works fine until I comment out Module.
My understanding is that the double pipes || and empty object {} will create an empty object in place of Module if it's undefined, but instead I'm getting an error in the console.
var Module = (function () {
var privateMethod = function () {
// private
};
var someMethod = function () {
// public
};
var anotherMethod = function () {
// public
};
return {
someMethod: someMethod,
anotherMethod: anotherMethod
};
})();
var ModuleTwo = (function (Module) {
Module.extension = function () {
// another method!
};
return Module;
})(Module || {});
Basically, there’s an error in the tutorial. One way to make things work was suggested by rplantiko, but it might be easier to just write window.Module || {} instead of Module || {}.
How things work here:
Accessing a non-existent property of any object yields undefined. However, referencing a variable that hasn’t been declared yields ReferenceError (so your understanding was a little bit off there).
Browser puts all global variables as properties onto global window object. Module in the tutorial is a global variable, because it’s declared outside all functions, so you can access it via window.Module, which will not cause ReferenceError if undefined (per previous point).
It might be a good practice to explicitly assign to window any global variable you define (e.g., do window.Module = (function () { … if you intend to make Module global), but that’s arguable and out of scope of this discussion.
When you apply the function defining your 2nd module to (Module || {}), the symbol Module cannot be resolved if the Module hasn't been declared earlier, which always gives a JavaScript error. If you want the 2nd Module to be defined even in the absence of the first Module, try the following:
var ModuleTwo = (function(Module) {
...
})(typeof Module == 'object' ? Module : {} );
I just started learning patterns in JavaScript, and getting used to writing JavaScript like this:
(function(window){
var privateVar;
var privateFunc = function(param){
//do something
}
return{
publicFunc: function(){
do something
}
}(window));
But recently I found some scripts that write something like this in the beginning:
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('something', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.something = factory(root);
}
})(window || this, function (root) {
var privateVar;
var privateFunc = function(param){
//do something
}
return{
publicFunc: function(){
do something
}
});
So, what does this piece of code in the beginning mean? What is the difference between that and with this module export technique:
var MODULE = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
TL;DR: JavaScript modules are loaded in different environments (different module loading systems, or no proper module system at all). The code you have is some boiler-plate code that lets you load a module in these different environments correctly, in a clean way.
In more detail: the actual definition you give is a "factory function": a function that returns the module contents when evaluated. A factory function is a very flexible thing that can be used in a variety of ways.
Browser globals
This is essentially your third example. Here, the factory function is executed immediately, and assigned to a global variable:
var MyModule = (function () {
// this is the factory function
})(); // execute immediately
The result is that other modules can reference this module by using the global variable - but this means you have to be careful to load all the modules in the correct order.
Asynchronous Module Definitions
Asynchronous Module Definition syntax is a pretty simple syntax, which provides a function called define() (spec here). This lets you describe modules by providing their dependencies and the factory function:
define('module-name', ['dep1', 'dep2'], function (dep1, dep2) {
...
});
So here, module-name is defined, but the factory function will only be executed when all the dependencies are loaded - this means that you can load the module definitions in any order, and the module loader is responsible for executing them all properly.
CommonJS
In CommonJS environments (such as Node.js, which runs in the command line or on a server), there is a global(-ish) object called module. Whatever you assign to module.exports is considered to be the value of the module.
If you want to use this with a factory function, it's pretty similar to the browser globals scenario, just that you assign it to module.exports:
module.exports = (function () {
// this is the factory function
})(); // execute immediately
Option (d): All of the above
It's possible to detect which module loaders are available by inspecting the environment (e.g. typeof define and typeof module).
The code block at the top detects which module loader is available and uses the factory function with AMD, CommonJS or browser globals, depending which is available.
While you could in theory do this inline in your code, separating it out to the top is nice and neat.
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.