BananaAcid
BananaAcid

Reputation: 3491

How and why does `module.exports = {__dirname}` work?

How does the code from here work - and why? The object notation does not seem to be satisfied. I find it rather confusing. What does this refer to in the docs @Mozilla or @NodeJS ?

File expose.js:

module.exports = {__dirname};

File use.mjs:

import expose from './expose.js';
const {__dirname} = expose;

So shouldn't this actually work, importing only key from the object, in use.mjs? (which doesn't ... but above does!)

import {__dirname} from './expose.js';

edit: I usually do something like import electron, {ipcMain, session} from 'electron'; - importing the whole name space, then specific parts directly as needed. As well as import {inspect} from 'util';. So deconstruction should be in place here

edit 2: see this post, from the thread mentioned by willascend below. The No. part explains what the problem with the line in my question was.

Upvotes: 0

Views: 1152

Answers (2)

willascend
willascend

Reputation: 1533

This is just a simple object literal with the property name matching the value:

let ___test = 'this is a string... could be a path';
let object = {___test};

console.log(object);

Using module.exports, you've exported an object. When importing using the module system, you essentially have a module scoped object, expose. You then destructure that object's __dirname property when defining {__dirname}. I haven't tested it, but you should be able to just import __dirname as a named import like so (though you'd likely run into a conflict for the variable name):

import __dirname from './expose.js';

EDIT: Did some testing, when you do the above import, you get your exported object, so you would still need to destructure after importing (and of course, destructure into a new variable):

import __dirname from './expose.js';
const {__dirname: dirname} = __dirname;
console.log(dirname);

After some googling, it appears you cannot destructure an object when performing an ES6 import. The syntax appears similar to destructuring an object but it is not. What you are doing when you do the following is actually import variables that have been exported as named exports.

test.mjs

export const __dirname = 'this is a path';

test-import.mjs

import { __dirname } from './test.mjs';
console.log(__dirname);

Note that I didn't use export const __dirname = __dirname;, or even export const dirname = __dirname;. This is because node specific globals aren't available in .mjs files currently. So, in your example, expose.js is still a standard .js file which has access to both the module and __dirname globals. The __dirname value is then exported as a property of the default commonjs export object (i.e. module.exports = {__dirname}), which is then made available as the default export when importing in your use.mjs file. The expose variable is the module.exports object literal that was exported. Once it's been initialized as an imported variable, you can then destructure out the __dirname value.

Hope this helps.

These other sources were helpful for me in understanding this as well: Destructuring a default export object https://github.com/babel/babel-loader/issues/194#issuecomment-168579479 https://github.com/nodejs/node/issues/16844#issuecomment-342245465

Upvotes: 2

NoobTW
NoobTW

Reputation: 2564

This is object shorthand in ES2015 (MDN).

{__dirname} is equal to {__dirname: __dirname}

For example:

var a = 'foo', b = 42, c = {};
var o = {a, b, c};

console.log(o);

Upvotes: 0

Related Questions