这两个module.exports有什么区别?

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

所以第一个是这样的:

myFile.js

var name = "Peter";

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

还有第二个

myFile.js

module.exports = function () {

  var name = 'Mary';

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

  return {
    sayHello : sayHello
  };

}();

本质上是一样的吧?如果不是,每种方法有什么区别,优缺点是什么?

对我来说是一样的。

也许第一个例子更常见。

根据您的其余代码,您可以同时使用两者。

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/

是的,它们基本上是一样的。你只是不需要第二个例子的冗长。

在第一个示例中,您将命名的 属性 添加到由 node.js 注入的现有 module.exports 对象中,在第二个示例中,您将覆盖原始对象 - 有消费端没有区别。

为什么我们需要模块?

当您有这样的代码时:

// 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());

这将导致错误,因为 a 变量已被第一个模块占用。您需要以某种方式定义模块。

使用前缀

通过旧式过程式编程,您会为单独的模块添加前缀:

// 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());

但这会降低代码的可读性。

使用闭包

到 javascript 你有了闭包,这让事情变得更容易了:

// 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());

但是您仍然在一个文件中包含不同的模块,因此该文件将非常大且难以维护。

使用 node.js 模块加载器

通过node.js你可以将不同模块的代码移动到单独的文件中,这样维护不同模块的代码会很容易,因为你可以找到很多相关的代码部分更快:

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());

您可以在浏览器中执行相同的操作

到目前为止,我能想出的最简单的 node.js 风格的浏览器模块加载器是:

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];
};

当然。使用 browserify、webpack、require.js 和其他更复杂的库要安全得多,我只是想告诉你,写一个加载器并不难。

我们从这一切中学到了什么?

node.js模块和闭包都是为了模块化。你不应该混用它们,因为它们解决的是同一个问题,混用只会导致混乱!