5 ms·
Your first Node.js module
- tferris 14y agoSlightly 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.
- tg3 14y agoThe error that is thrown towards the end of this example should probably be passed back to the callback as an argument (e.g. callback(error, result)) instead. Throwing errors in an asynchronous context can have messy results for trying to handle them. http://benno.id.au/blog/2011/08/08/nodejs-exceptions http://benno.id.au/blog/2011/08/08/nodejs-exceptions is a good explanation.
- c_t_montgomery 14y agoGreat point. I'll update the gist. Thanks for bringing this up!
- secoif 14y agoIt should also be pointed out you rarely need to edit the package.json manually: npm init: Prompts for basic/common package.json entries npm install --save: Install a module and place into dependencies npm install --save-dev: Install a module and place into dev dependencies npm install --save-optional: Install a module and place into optional dependencies http://blog.timoxley.com/post/22371787222/handy-new-options-for-npm-install http://blog.timoxley.com/post/22371787222/handy-new-options-...
- c_t_montgomery 14y agoI was debating whether or not to put it in there. Since Isaac mentions it in his article that I link to, I figured most people would see it there. Very valid point though. I think I may edit the post and put it up there. Thanks!
- c_t_montgomery 14y ago...and the post has been updated. Thanks again.
- phase_9 14y agoI liked the part where you encouraged the developer to think about how the API will be consumed by the end user; however even a brief mention of some BDD / Unit tests here would have been nice (:
- c_t_montgomery 14y agoI agree it would have been nice. Apologies for not including it.
- aeurielesn 14y agoJust for the record, I think you should have used `encodeURIComponent` instead of `encodeURI`. And in `exports.info` as well.
- c_t_montgomery 14y agoAh great catch. I just changed it. Thanks!