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 : {} );
Related
On this page (http://docs.nodejitsu.com/articles/getting-started/what-is-require), it states that "If you want to set the exports object to a function or a new object, you have to use the module.exports object."
My question is why.
// right
module.exports = function () {
console.log("hello world")
}
// wrong
exports = function () {
console.log("hello world")
}
I console.logged the result (result=require(example.js)) and the first one is [Function] the second one is {}.
Could you please explain the reason behind it? I read the post here: module.exports vs exports in Node.js . It is helpful, but does not explain the reason why it is designed in that way. Will there be a problem if the reference of exports be returned directly?
module is a plain JavaScript object with an exports property. exports is a plain JavaScript variable that happens to be set to module.exports.
At the end of your file, node.js will basically 'return' module.exports to the require function. A simplified way to view a JS file in Node could be this:
var module = { exports: {} };
var exports = module.exports;
// your code
return module.exports;
If you set a property on exports, like exports.a = 9;, that will set module.exports.a as well because objects are passed around as references in JavaScript, which means that if you set multiple variables to the same object, they are all the same object; so then exports and module.exports are the same object.
But if you set exports to something new, it will no longer be set to module.exports, so exports and module.exports are no longer the same object.
Renee's answer is well explained. Addition to the answer with an example:
Node does a lot of things to your file and one of the important is WRAPPING your file. Inside nodejs source code "module.exports" is returned. Lets take a step back and understand the wrapper. Suppose you have
greet.js
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
the above code is wrapped as IIFE(Immediately Invoked Function Expression) inside nodejs source code as follows:
(function (exports, require, module, __filename, __dirname) { //add by node
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
}).apply(); //add by node
return module.exports; //add by node
and the above function is invoked (.apply()) and returned module.exports.
At this time module.exports and exports pointing to the same reference.
Now, imagine you re-write
greet.js as
exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
the output will be
[Function]
{}
the reason is : module.exports is an empty object. We did not set anything to module.exports rather we set exports = function()..... in new greet.js. So, module.exports is empty.
Technically exports and module.exports should point to same reference(thats correct!!). But we use "=" when assigning function().... to exports, which creates another object in the memory. So, module.exports and exports produce different results. When it comes to exports we can't override it.
Now, imagine you re-write (this is called Mutation)
greet.js (referring to Renee answer) as
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
the output will be
{ a: [Function] }
{ a: [Function] }
As you can see module.exports and exports are pointing to same reference which is a function. If you set a property on exports then it will be set on module.exports because in JS, objects are pass by reference.
Conclusion is always use module.exports to avoid confusion.
Hope this helps. Happy coding :)
Also, one things that may help to understand:
math.js
this.add = function (a, b) {
return a + b;
};
client.js
var math = require('./math');
console.log(math.add(2,2); // 4;
Great, in this case:
console.log(this === module.exports); // true
console.log(this === exports); // true
console.log(module.exports === exports); // true
Thus, by default, "this" is actually equals to module.exports.
However, if you change your implementation to:
math.js
var add = function (a, b) {
return a + b;
};
module.exports = {
add: add
};
In this case, it will work fine, however, "this" is not equal to module.exports anymore, because a new object was created.
console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
And now, what will be returned by the require is what was defined inside the module.exports, not this or exports, anymore.
Another way to do it would be:
math.js
module.exports.add = function (a, b) {
return a + b;
};
Or:
math.js
exports.add = function (a, b) {
return a + b;
};
Rene's answer about the relationship between exports and module.exports is quite clear, it's all about javascript references. Just want to add that:
We see this in many node modules:
var app = exports = module.exports = {};
This will make sure that even if we changed module.exports, we can still use exports by making those two variables point to the same object.
node does something like this:
module.exports = exports = {}
module.exports and exports refer to same object.
This is done just for convenience.
so instead of writing something like this
module.exports.PI = 3.14
we can write
exports.PI = 3.14
so it is ok to add a property to exports but assigning it to a different object is not ok
exports.add = function(){
.
.
}
↑ this is OK and same as module.exports.add = function(){...}
exports = function(){
.
.
}
↑ this is not ok and and empty object will be returned as module.exports still refers to {} and exports refer to different object.
There are two difference between module.exports and exports
When export a single class, variable or function from one module to another module, we use the module.exports. But export to multiple variables or functions from one module to another, we use exports.
module.exports is the object reference that gets returned from the require() calls. But exports is not returned by require().
see more details with examples >> link
As all answers posted above are well explained, I want to add something which I faced today.
When you export something using exports then you have to use it with variable. Like,
File1.js
exports.a = 5;
In another file
File2.js
const A = require("./File1.js");
console.log(A.a);
and using module.exports
File1.js
module.exports.a = 5;
In File2.js
const A = require("./File1.js");
console.log(A.a);
and default module.exports
File1.js
module.exports = 5;
in File2.js
const A = require("./File2.js");
console.log(A);
myTest.js
module.exports.get = function () {};
exports.put = function () {};
console.log(module.exports)
// output: { get: [Function], put: [Function] }
exports and module.exports are the same and a reference to the same object. You can add properties by both ways as per your convenience.
You can think of exports as a shortcut to module.exports within a
given module. In fact, exports is just a variable that gets
initialized to the value of module.exports before the module is
evaluated. That value is a reference to an object (empty object in
this case). This means that exports holds a reference to the same
object referenced by module.exports. It also means that by assigning
another value to exports it's no longer bound to module.exports.
This explanation from MDN is the most clear to me.
Basically, there is one object in memory which is referenced by 2 variables - exports and module.exports.
exports.a = 23
equals
module.exports = {a:23}
But,
exports = {a:23}
does not equal
module.exports = {a:23}
When you assign a new object to exports variable directly, then that variable does not refer to module.exports anymore.
On this page (http://docs.nodejitsu.com/articles/getting-started/what-is-require), it states that "If you want to set the exports object to a function or a new object, you have to use the module.exports object."
My question is why.
// right
module.exports = function () {
console.log("hello world")
}
// wrong
exports = function () {
console.log("hello world")
}
I console.logged the result (result=require(example.js)) and the first one is [Function] the second one is {}.
Could you please explain the reason behind it? I read the post here: module.exports vs exports in Node.js . It is helpful, but does not explain the reason why it is designed in that way. Will there be a problem if the reference of exports be returned directly?
module is a plain JavaScript object with an exports property. exports is a plain JavaScript variable that happens to be set to module.exports.
At the end of your file, node.js will basically 'return' module.exports to the require function. A simplified way to view a JS file in Node could be this:
var module = { exports: {} };
var exports = module.exports;
// your code
return module.exports;
If you set a property on exports, like exports.a = 9;, that will set module.exports.a as well because objects are passed around as references in JavaScript, which means that if you set multiple variables to the same object, they are all the same object; so then exports and module.exports are the same object.
But if you set exports to something new, it will no longer be set to module.exports, so exports and module.exports are no longer the same object.
Renee's answer is well explained. Addition to the answer with an example:
Node does a lot of things to your file and one of the important is WRAPPING your file. Inside nodejs source code "module.exports" is returned. Lets take a step back and understand the wrapper. Suppose you have
greet.js
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
the above code is wrapped as IIFE(Immediately Invoked Function Expression) inside nodejs source code as follows:
(function (exports, require, module, __filename, __dirname) { //add by node
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
}).apply(); //add by node
return module.exports; //add by node
and the above function is invoked (.apply()) and returned module.exports.
At this time module.exports and exports pointing to the same reference.
Now, imagine you re-write
greet.js as
exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
the output will be
[Function]
{}
the reason is : module.exports is an empty object. We did not set anything to module.exports rather we set exports = function()..... in new greet.js. So, module.exports is empty.
Technically exports and module.exports should point to same reference(thats correct!!). But we use "=" when assigning function().... to exports, which creates another object in the memory. So, module.exports and exports produce different results. When it comes to exports we can't override it.
Now, imagine you re-write (this is called Mutation)
greet.js (referring to Renee answer) as
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
the output will be
{ a: [Function] }
{ a: [Function] }
As you can see module.exports and exports are pointing to same reference which is a function. If you set a property on exports then it will be set on module.exports because in JS, objects are pass by reference.
Conclusion is always use module.exports to avoid confusion.
Hope this helps. Happy coding :)
Also, one things that may help to understand:
math.js
this.add = function (a, b) {
return a + b;
};
client.js
var math = require('./math');
console.log(math.add(2,2); // 4;
Great, in this case:
console.log(this === module.exports); // true
console.log(this === exports); // true
console.log(module.exports === exports); // true
Thus, by default, "this" is actually equals to module.exports.
However, if you change your implementation to:
math.js
var add = function (a, b) {
return a + b;
};
module.exports = {
add: add
};
In this case, it will work fine, however, "this" is not equal to module.exports anymore, because a new object was created.
console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
And now, what will be returned by the require is what was defined inside the module.exports, not this or exports, anymore.
Another way to do it would be:
math.js
module.exports.add = function (a, b) {
return a + b;
};
Or:
math.js
exports.add = function (a, b) {
return a + b;
};
Rene's answer about the relationship between exports and module.exports is quite clear, it's all about javascript references. Just want to add that:
We see this in many node modules:
var app = exports = module.exports = {};
This will make sure that even if we changed module.exports, we can still use exports by making those two variables point to the same object.
node does something like this:
module.exports = exports = {}
module.exports and exports refer to same object.
This is done just for convenience.
so instead of writing something like this
module.exports.PI = 3.14
we can write
exports.PI = 3.14
so it is ok to add a property to exports but assigning it to a different object is not ok
exports.add = function(){
.
.
}
↑ this is OK and same as module.exports.add = function(){...}
exports = function(){
.
.
}
↑ this is not ok and and empty object will be returned as module.exports still refers to {} and exports refer to different object.
There are two difference between module.exports and exports
When export a single class, variable or function from one module to another module, we use the module.exports. But export to multiple variables or functions from one module to another, we use exports.
module.exports is the object reference that gets returned from the require() calls. But exports is not returned by require().
see more details with examples >> link
As all answers posted above are well explained, I want to add something which I faced today.
When you export something using exports then you have to use it with variable. Like,
File1.js
exports.a = 5;
In another file
File2.js
const A = require("./File1.js");
console.log(A.a);
and using module.exports
File1.js
module.exports.a = 5;
In File2.js
const A = require("./File1.js");
console.log(A.a);
and default module.exports
File1.js
module.exports = 5;
in File2.js
const A = require("./File2.js");
console.log(A);
myTest.js
module.exports.get = function () {};
exports.put = function () {};
console.log(module.exports)
// output: { get: [Function], put: [Function] }
exports and module.exports are the same and a reference to the same object. You can add properties by both ways as per your convenience.
You can think of exports as a shortcut to module.exports within a
given module. In fact, exports is just a variable that gets
initialized to the value of module.exports before the module is
evaluated. That value is a reference to an object (empty object in
this case). This means that exports holds a reference to the same
object referenced by module.exports. It also means that by assigning
another value to exports it's no longer bound to module.exports.
This explanation from MDN is the most clear to me.
Basically, there is one object in memory which is referenced by 2 variables - exports and module.exports.
exports.a = 23
equals
module.exports = {a:23}
But,
exports = {a:23}
does not equal
module.exports = {a:23}
When you assign a new object to exports variable directly, then that variable does not refer to module.exports anymore.
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.
I am new to Node.js and trying to figure out how to request an object from a separate file (rather than just requesting a function) but everything I try--exports,module-exports,etc--is failing.
So, for example, if I have foo.js:
var methods = {
Foobar:{
getFoo: function(){return "foo!!";},
getBar: function(){return "bar!!";}
}
};
module.exports = methods;
And now I want to call a function within an object of foo.js from index.js:
var m = require('./foo');
function fooMain(){
return m.Foobar.getFoo();
};
How do I do this? I have tried all sorts of combinations of exports and module-exports but they seem to only work if I call a discrete function that is not part of an object.
You said that you tried exports, but your code doesn't show it. Anything that you want to be visible from outside your module must be assigned to (or otherwise be referable from) module.exports. In your case, where you have an object already, you can just assign it to module.exports:
var methods = {
...
};
// You must export the methods explicitly
module.exports = methods;
module.exports isn't magic, it's a normal object, and you can treat it as such. Meaning that you could have assigned your methods directly to it, as in:
module.exports.Foobar = {};
module.exports.Foobar.getFoo = function() { ... };
...
Or, as you probably know, you could event replace it with a function:
module.exports = function() { return "It's ALWAYS over 9000!!!!"; };
Only after exporting will you be able to use anything in another module.
I'm working with the Google Closure Compiler in ADVANCED_OPTIMIZATIONS compilation level and have started to annotate my constructors because I get all kinds of warnings:
WARNING - dangerous use of the global this object
For my 'constructor' type functions I'll annotate them like this:
/**
* Foo is my constructor
* #constructor
*/
Foo = function() {
this.member = {};
}
/**
* does something
* #this {Foo}
*/
Foo.prototype.doSomething = function() {
...
}
That seems to work fine, however what if I have a 'singleton' object that isn't constructed with var myFoo = new Foo();
I couldn't find in the documentation how to annotate this type of object because its type is just object right?
Bar = {
member: null,
init: function() {
this.member = {};
}
};
The preferred way of creating singletons in Closure is like this:
/** #constructor */
var Bar = function() { };
goog.addSingletonGetter(Bar);
Bar.prototype.member = null;
Bar.prototype.init = function() {
this.member = {};
};
This allows for lazy instantiation of the singleton. Use it like this:
var bar1 = Bar.getInstance();
var bar2 = Bar.getInstance();
bar1.init();
console.log(bar2.member);
Keep in mind that this doesn't prevent people from using the constructor to create instances of Bar.
This is exactly the type of potential bug that "dangerous use of this" warns you against. In your example, the Closure Compiler may try to "flatten" your code to:
Bar$member = null;
Bar$init = function() { this.member = {}; };
NOTE: The Closure Compiler currently will not flatten a namespace that is declared as a global object (i.e. without the "var" keyword in front), so your code may still work now. However, there is no telling that it won't do that in a future version and your code will suddenly break without warning.
Of course, then "Bar$member" and "Bar$init" will be renamed to "a" and "b" respectively. This is called "namespace flattening" or "collapsing of properties".
You can immediately see that your code no longer works correctly. Before compilation, if you write:
Bar.init();
this will refer to Bar. However, after compilation it becomes:
Bar$init();
this will no longer refer to Bar. Instead it refers to the global object.
This is way the compiler is trying to warn you that using "this" in such a way is "dangerous", because "this" may be changed to refer to the "global" object. That's the true meaning of the warning.
In short, DO NOT DO THIS. This type of coding style creates bugs that are very difficult to track down.
Modify your code this way:
var Bar = { // Closure Compiler treats globals and properties on global differently
member: null,
init: function() { Bar.member = {}; }
};
or use a closure:
var Bar = (function() {
var member = null;
return {
init: function() { member = {}; }
};
})();
When using the Closure Compiler in Advanced Mode, do not try to get rid of warnings by annotating them away. Warnings are there for a reason -- they try to warn you about something.