简体   繁体   中英

What's the difference between these two module.exports?

So the first one being something like:

myFile.js

var name = "Peter";

module.exports.sayHello = function () {
  console.log('Hello ' + name);
}

And the second one

myFile.js

module.exports = function () {

  var name = 'Mary';

  function sayHello () {
    console.log('Hello ' + name);
  }

  return {
    sayHello : sayHello
  };

}();

Essentially it's the same thing right? If not, what's the difference and what's the pros and cons of each method?

For me it's the same thing.

Maybe the first example is more common.

You can use both, according to the rest of your code.

Yes they are basically the same. You just don't need the verbosity of the second example.

In the first example you are adding a named property to the already existing module.exports object injected by node.js, in the second example you are overriding the original object - there is no difference for the consuming end.

Why do we need modules?

When you have a code like this:

// module 1
var a = 1;
var x = function (){
    return a;
};

// module 2
var a = 2; // duplicated variable declaration
var y = function (){
    return a;
};

// main
console.log(x()); // BUG: this should read value from module 1 instead of module 2
console.log(y());

It will lead to error, since the a variable was already taken by the first module. You need to define modules somehow.

Using a prefix

By old-style procedural programming you would add a prefix to separate modules:

// module 1
var m1_a = 1;
var m1_x = function (){
    return m1_a;
};

// module 2
var m2_a = 2;
var m2_y = function (){
    return m2_a;
};

// main
console.log(m1_x());
console.log(m2_y());

But this makes the code less readable.

Using closures

By javascript you have closures, which make things a little bit easier:

// module 1
var x = (function (){
    var a = 1;
    var x = function (){
        return a;
    };
    return x;
})();

// module 2
var y = (function (){
    var a = 2;
    var y = function (){
        return a;
    };
    return y;
})();

// main
console.log(x());
console.log(y());

But still you have different modules in a single file, so that file will be really big and hard to maintain.

Using the node.js module loader

By node.js you can move the code of different modules to separate files, so it will be easy to maintain the code of different modules, since you will be able to find the relevant part of the code much faster:

m1.js

var a = 1;
var x = function (){
    return a;
};
module.exports = x;

m2.js

var a = 2;
var y = function (){
    return a;
};
module.exports = y;

main.js

var x = require("m1");
var y = require("m2");

console.log(x());
console.log(y());

You can do the same in the browser

The simplest node.js style browser module loader I could come up with so far, is this:

var cache = {};

function require(name){
    if (name in cache)
        return cache[name];
    var uri = "./" + name + ".js";
    var xhr = new XMLHttpRequest();
    xhr.open("GET", uri, false);
    xhr.send(null);
    var moduleCode = xhr.responseText;
    var fn = new Function("module", moduleCode);
    var module = {};
    fn(module);
    cache[name] = module.exports;
    return cache[name];
};

Ofc. it is much safer to use browserify, webpack, require.js and other more sophisticated libs, I just wanted to show you, it is not that hard to write a loader.

What did we learn from all of this?

Both node.js modules and closures are for modularization. You should not mix them, since they solve the same problem, and mixing them will lead only to confusion!

Lets go to the basics of module mechanism in NodeJS. For every JS file the ground reality is which happens on the top of file:

var exports = module.exports = {};
  1. Whenever we try to fetch the import it retrieves module.exports only
  2. If we do both in Js file
 exports.key = "key1" and module.exports = {key : "VAL"}

only the module.exports is fetched during the import according to the rule.

Now coming back to your question Adding module.exports.sayHello will add the reference to the {} which is common with exports variable too.

However if you do

 module.exports = function () {} // some function

it breaks the chain and it is only assigned to module.exports and not exports variable.

This is why if we add any key to exports variable is retrieved via module.exports during import! Hope it clarifies! A very good article on this https://www.sitepoint.com/understanding-module-exports-exports-node-js/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM