3 ms·
Slightly OT: does anyone have a good explanation for module.exports vs exports and for the expression 'exports = module.exports = someFunction' often found in m
by tferris 14y ago
Slightly OT: does anyone have a good explanation for module.exports vs exports and for the expression 'exports = module.exports = someFunction' often found in modules?
- deleted 14y ago[deleted]
- mattyb 14y agoAccording to the documentation, they are the same: http://nodejs.org/docs/v0.6.18/api/modules.html#modules_the_module_object http://nodejs.org/docs/v0.6.18/api/modules.html#modules_the_...
- strager 14y agoReassigning the `exports` variable does not change the return value of `require`. The return value of `require` is `module.exports`, which may be reassigned. Initially, the global `exports` variable is set to the same value as `module.exports`. Writing `exports = module.exports = ...` ensures they have the same value as you would expect.
- tferris 14y ago> Writing `exports = module.exports = ...` ensures they have the same value as you would expect. But where should they have the same value? I thought require returns just module.exports if it exists and ignores exports.
- secoif 14y ago'this' is also the same as exports. Initially, they all have the same value, they all point at the same object. If you assign module.exports to a new object (vs simply adding properties to the existing object) it will ignore the value of exports and this. It's incredibly confusing and they should have just picked one way to export data, instead of three.
- smagch 14y ago=== hoge.js === module.exports = exports = { hello: 'hello', world: 'world' }; exports.yetAnother = 'yet another exports key'; === and this yield require('./hoge') -> { hello: 'hello', world: 'world', yetAnother: 'yet another exports key' } But, when hoge.js is === hoge.js === module.exports = { hello: 'hello', world: 'world' }; exports.yetAnother = 'yet another exports key'; === require('./hoge') -> // { hello: 'hello', world: 'world' } or === hoge.js === exports = { hello: 'hello', world: 'world' }; exports.yetAnother = 'yet another exports key'; === require('./hoge') -> // {}
- tferris 14y agoSo you reassigned module.exports to exports in order to get all objects assigned to both module.exports and exports otherwise objects assigned to module.exports would override those assigned to exports which would stay ignored, right? But: to get all objects do I have to assign module.exports to exports (so change the order from your first example)?: exports = module.exports = { hello: 'hello', world: 'world' };
- smagch 14y agoI usually use just `module.export = {...}` in the bottom line when I want to export object by object literal. To be honest, I'm not quite sure about commonJS require implementation of nodeJS. But as long as I'm understand, 1. Use `module.exports` if you want to assign exports by object literal 2. Use `exports.[key]` if you want to assign exports brick by brick. 3. Use `exports = module.exports = {...}` or `module.exports = exports` if you want to ensure both functionality; you can assign `exports.[key] after assign exports by object literal.
- radagaisus 14y agoAlso, `this` is exported in modules.
- zeekay 14y agoI've noticed that, and have been taking advantage of it. Any downside to using `this`, besides potential scoping issues?
- radagaisus 14y agoNot that I've experienced. Another cool trick: modules make sense when you use packages, but they feel like PHP 4 when you just try to divide your code to several files. https://gist.github.com/2692091 https://gist.github.com/2692091 This fixes part of the problem, but what happens when you reference './models/user.js' from the file 'auth.js' but then auth grows in size and you decide to divide it and put it in auth/facebook.js, auth/twitter.js, etc. -- well, now you are fucked.
- secoif 14y agoYou shouldn't require using the extension. This gives you the flexibility to transparently change the file into a folder + index.*, then break functionality up into pieces that live inside that folder.
- radagaisus 14y agoStill, currently you need to require everything with a relative path unless it's inside node_modules.
- deleted 14y ago[deleted]
- tgasson 14y agoEvery module will have a `module` variable available to it. `module` defaults to { id: ... exports: {} parent:... filename:... loaded:... exited:... children:... paths:... } Whatever module.exports is at the end of the module is passed to the require statement. Every file essentially has two lines at the top. this = module.exports; var exports = module.exports; The first helps lazy developers by allowing exporting without explicitly saying so. Because of this, the following alone is a valid module that exports {foo:'bar'} foo = 'bar'; // can also be written as this.foo = 'bar'; And the second matches the CommonJS standard. So the following CommonJS module will work: exports.foo = 'bar'; If you assign module.exports at any time after using `this` or `exports`, module.exports will point to the new object, and anything on the original module.exports object wont be passed to the `require` call.