0

Javascript provides the global context via the 'windows' or 'globalThis' object:

var a = 10;
function f(s){console.log(s)}
globalThis["f"]("Hallo Welt")
console.log(globalThis.a);   
console.log(globalThis["a"]);

Is there a similar thing inside ES6-modules? Referring to the MDN WEB DOCS, If the source is loaded as a module (for HTML, this means adding type="module" to the tag), this is always undefined at the top level.

It seems, this was done intentionally, but maybe there is a workaround? As the module context is encapsulated, flooding the context with definitions seems to be less risky than flooding the global context.

Here is an example:

import * as library from "./library.js"
Object.assign(globalThis, library)  // -> expose all exports to the global Namespace

The result is the same as a named import, just you do not need to define import and export synchronously.

I would love to do the same with modules inside a module, just it does not seem to be possible.

Eckehard
  • 59
  • 4
  • 1
    What's the point? What would you do with the module context if you could access it? – Pointy Mar 12 '23 at 14:45
  • "*As the module context is encapsulated, flooding the context with definitions seems to be less risky than flooding the global context.*" No, it's not. It's still something *external* to your code that you'd be flooding with definitions. That can cause a problem whenever said external thing updates and now defines its own `foo` which you've also defined. Yes, if you control the module, that'd be "safer" (somewhat) but if you control the module, you can update it as you wish from where it's defined, not do it externally. Seems like [an XY problem](https://meta.stackexchange.com/q/66377). – VLAZ Mar 12 '23 at 16:53
  • Sounds a bit like a duplicate of [Is it possible to import variables in JavaScript (node.js)?](https://stackoverflow.com/q/21562973/1048572) or [Add variable to a scope / equivalent of window object](https://stackoverflow.com/q/24097767/1048572) – Bergi Mar 12 '23 at 17:14
  • Not exactly a duplicate, but a similar topic. Thank you for the hint, I will check this out. In the case of ES6 it seems, exposing the context via "this" was a hot topic when Modules have been introduced, but a decsion was made to set "this" to undefined in modules. As you might see in the example above, `Object.assign(moduleThis, library)` can be a convenient way to extend the context of a module. It´s just the same like named imports, just with a wildcard function. It is even not violating the encapsulation in any way. – Eckehard Mar 12 '23 at 17:50
  • @Eckehard There is no such "context" object that backs a module scope. The [esdicuss thread](https://esdiscuss.org/topic/this-inside-modules#content-30) you found is talking about the object that became `import.meta`. Nobody ever suggested to provide an object representation of the scope. – Bergi Mar 12 '23 at 18:00
  • I found some better duplicates. And actually it's possible to do what you want, using `eval`, see [here](https://stackoverflow.com/a/46977735/1048572) or [there](https://stackoverflow.com/a/56826876/1048572). That should suffice as the hack you want, or discourage you enough if you were not looking for a hack. – Bergi Mar 12 '23 at 18:05
  • @Bergi I´m not lookin for a "hack", just a more convenient way to deal with long export/import lists, if I simply want to import everything a module exports. Eval is no option, but I have seen your second link somewhere else: ~~~ import * as constants from './constants' const { A, B, C, } = constants; ~~~ This is really a strange feature, and not the perfect solution, but maybe a starting point. Thank you for your hints! – Eckehard Mar 12 '23 at 18:24
  • 1
    You shouldn't import everything, you should only import the things that you actually need. And you should inconvenience yourself to explicitly declare which identifier is imported from which module, as that makes code much easier to understand. Regarding "*`import * as constants from './constants' const { A, B, C, } = constants`*", I don't see why you wouldn't just write `import { A, B, C } from './constants';`? – Bergi Mar 12 '23 at 19:11

1 Answers1

3

The point of ES6 modules is that they're encapsulated, meaning nothing interferes with them and they don't interfere with anything else. Having a kind of globalThis would ruin the whole point because then you're allowing something to pierce that veil of encapsulation.

If you need to share stuff between modules, then use imports and exports, as they allow each module to control exactly what's inside of itself and what's in its namespace. If you need to import something in the middle of execution or conditionally, then use the asynchronous import() function.

Michael M.
  • 10,486
  • 9
  • 18
  • 34
  • A "modulThis" would not necessarily break encapsulation, if it is scoped. It´s just a different - and in some cases convenient - way to access the module context. – Eckehard Mar 12 '23 at 17:41