是module.exports等于出口

时间:2019-02-17 07:41:23

标签: javascript node.js

我是nodejs的新手, 尝试了解其他文件的包含功能。

我发现module.exportsexports可以解决我的问题, 但我不知道两者之间有什么区别。

我做了一些研究,发现exports = module.exports
参考:Understanding module.exports and exports in Node.js

var exports = module.exports = {};

但是我仍然不确定,所以我做了实验:

index.js

const lib1 = require('./lib1.js');
const lib2 = require('./lib2.js');
const lib3 = require('./lib3.js');
const lib4 = require('./lib4.js');

const func = () => {
    return 'attr2';
};

var lib = {};
var lib = {
    attr1: 'attr1',
    attr2_1: func,
    attr2_2: func(),
    attr3: () => {
        return 'attr3 (closure)';
    }
};

// using object variable on local file
console.log(lib.attr1);
console.log(lib.attr2_1());
console.log(lib.attr2_2);
console.log(lib.attr3());

console.log('# Case1 ----');

console.log(lib1.attr1);
console.log(lib1.attr2_1());
console.log(lib1.attr2_2);
console.log(lib1.attr3());

console.log('# Case2 ----');

console.log(lib1.attr1);
console.log(lib1.attr2_1());
console.log(lib1.attr2_2);
console.log(lib1.attr3());

console.log('# Case3 ----');

console.log(lib3.attr1);
console.log(lib3.attr2_1());
console.log(lib3.attr2_2);
console.log(lib3.attr3());

console.log('# Case4 ----');

console.log(lib4.attr1);
console.log(lib4.attr2_1());
console.log(lib4.attr2_2);
console.log(lib4.attr3());

lib1.js

const func = () => {
    return 'attr2';
}

// Case1 : This work
module.exports.attr1 = 'attr1';
module.exports.attr2_1 = func;
module.exports.attr2_2 = func();
module.exports.attr3 = () => {
    return 'attr3 (closure)';
};

lib2.js

const func = () => {
    return 'attr2';
}

// Case2 : This work
module.exports = {
    attr1: 'attr1',
    attr2_1: func,
    attr2_2: func(),
    attr3: () => {
        return 'attr3 (closure)';
    }
};

lib3.js

const func = () => {
    return 'attr2';
}

// Case3 : This work
exports.attr1 = 'attr1';
exports.attr2_1 = func;
exports.attr2_2 = func();
exports.attr3 = () => {
    return 'attr3 (closure)';
};

lib4.js

const func = () => {
    return 'attr2';
}

// Case4 : Not work!
exports = {
    attr1: 'attr1',
    attr2_1: func,
    attr2_2: func(),
    attr3: () => {
        return 'attr3 (closure)';
    }
};

case4将返回错误:(来自vscode调试)

...

# Case4 ----
undefined
C:\Users\Scott\Documents\module_export\index.js:49
console.log(lib4.attr2_1());
                 ^

TypeError: lib4.attr2_1 is not a function
    at Object.<anonymous> (C:\Users\Scott\Documents\module_export\index.js:49:18)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:282:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)

case1、2、3 =>正常。

但是为什么case4是错误的? var exports = module.exports = {};不正确吗?

3 个答案:

答案 0 :(得分:1)

您在这里做什么

var exports = module.exports = {};
exports = {
    attr1: 'attr1',
    attr2_1: func,
    attr2_2: func(),
    attr3: () => {
        return 'attr3 (closure)';
    }
};

正在将名为exports的变量重新分配给一个全新的对象。名为exports的变量不再与module.exports指向同一对象; module.exports保持不变,为空对象。因此,当其他模块尝试从lib4导入时,它们只会得到一个空对象。

您必须像情况3一样对exports变量进行变异,或者像您一样在exports上重新分配module属性在情况2中做(或在情况1中对现有的exports对象进行突变)。

这与导入/导出没有特别关系:可以在此处看到相同的行为:

// boilerplate, so that the live snippet will run
const module = {};

var exports = module.exports = {};
const func = () => {
    return 'attr2';
}

// Case4 : Not work!
exports = {
    attr1: 'attr1',
    attr2_1: func,
    attr2_2: func(),
    attr3: () => {
        return 'attr3 (closure)';
    }
};

// module.exports is still the empty object:
console.log(module.exports.attr1);

或者在这里:

var obj1 = {};
var obj2 = obj1;
obj2 = { foo: 'foo' }; // reassigning obj2 does not affect obj1
console.log(obj1.foo); // undefined, obj1 is just an empty object, after all

除非module.exports以某种方式填充,否则不会导出任何内容。

答案 1 :(得分:1)

就像您提到的,exports是对module.exports的引用。导入模块后,将返回module.exports中的值。

通过将exports分配给另一个对象,您并没有更改module.exports的值,因此不会出现此错误。

答案 2 :(得分:-1)

在节点js中,exports是一个获取器/设置器。一旦尝试获取导出值(exports),它将返回module.exports。但是,如果您尝试设置导出值(exports = something),它将更改module.exports的值。