module.exports vs exports

    很多时候,你会看到,在Node环境中,有两种方法可以在一个模块中输出变量:

    方法一:对module.exports赋值:

    // hello.js



    function hello() {

    console.log('Hello, world!');

    }



    function greet(name) {

    console.log('Hello, ' + name + '!');

    }



    function hello() {

    console.log('Hello, world!');

    }



    module.exports = {

    hello: hello,

    greet: greet

    };

    方法二:直接使用exports:

    // hello.js



    function hello() {

    console.log('Hello, world!');

    }



    function greet(name) {

    console.log('Hello, ' + name + '!');

    }



    function hello() {

    console.log('Hello, world!');

    }



    exports.hello = hello;

    exports.greet = greet;

    但是你不可以直接对 exports 赋值:

    // 代码可以执行,但是模块并没有输出任何变量:

    exports = {

    hello: hello,

    greet: greet

    };

    如果你对上面的写法感到十分困惑,不要着急,我们来分析Node的加载机制:

    首先,Node会把整个待加载的 hello.js 文件放入一个包装函数 load 中执行。在执行这个 load() 函数前,Node准备好了module变量:

    var module = {

    id: 'hello',

    exports: {}

    };

    load() 函数最终返回 module.exports

    var load = function (exports, module) {

    // hello.js的文件内容



    // load函数返回:

    return module.exports;

    };



    var exported = load(module.exports, module);

    也就是说,默认情况下,Node准备的 exports 变量和 module.exports 变量实际上是同一个变量,并且初始化为空对象 {} ,于是,我们可以写:

    exports.foo = function () { return 'foo'; };

    exports.bar = function () { return 'bar'; };

    也可以写:

    module.exports.foo = function () { return 'foo'; };

    module.exports.bar = function () { return 'bar'; };

    换句话说,Node默认给你准备了一个空对象 {} ,这样你可以直接往里面加东西。

    但是,如果我们要输出的是一个函数或数组,那么,只能给 module.exports 赋值:

    module.exports = function () { return 'foo'; };

    exports 赋值是无效的,因为赋值后, module.exports 仍然是空对象 {}