I've always wondered how you always have access to require
and module.exports
in any .js
files running with node. I recently found something cool.
If you console.log
arguments
in a file, and run it with node. For eg:
// someFile.js console.log(arguments);
We actually get arguments:
[Arguments] { '0': {}, '1': [Function: require] { resolve: [Function: resolve] { paths: [Function: paths] }, main: Module { id: '.', path: '/someFolder', exports: {}, parent: null, filename: '/someFolder/someFile.js', loaded: false, children: [], paths: [Array] }, extensions: [Object: null prototype] { '.js': [Function], '.json': [Function], '.node': [Function] }, cache: [Object: null prototype] { '/someFolder/someFile.js': [Module] } }, '2': Module { id: '.', path: '/someFolder', exports: {}, parent: null, filename: '/someFolder/someFile.js', loaded: false, children: [], paths: [ 'someFolder/node_modules', '/Users/username/node_modules', '/Users/node_modules', '/node_modules' ] }, '3': '/someFolder/someFile.js', '4': '/someFolder' }
Every time you run a file using node (eg: node someFile.js
), the file is loaded inside an IIFE (immediately invoked function expression).
and the function looks like this:
(function (exports, require, module, __filename, __dirname)())
exports
is essentially an alias or a reference to module.exports
, which is why you can do this:
exports.foo = () => console.log("foo"); // OK
but not this:
exports = () => console.log("foo"); // NOT OK
Note: I learned this thanks to Sameer Buna's "You don't know node" talk from ForwardJS San Francisco 2017.
The source code for this website can be found here under an MIT license