How require and module.exports in node works

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.