I have a module called fooModule
. Inside this module, I import fooModule
(itself):
import * as fooModule from './fooModule';
export function logFoo() {
console.log(fooModule)
}
When logFoo()
is called, I can see all of the exports of the fooModule.
How does this work?
I have a module called fooModule
. Inside this module, I import fooModule
(itself):
import * as fooModule from './fooModule';
export function logFoo() {
console.log(fooModule)
}
When logFoo()
is called, I can see all of the exports of the fooModule.
How does this work?
- 1 what you want to do ? – anshuVersatile Commented Oct 25, 2016 at 13:03
- 8 Imports aren't imperative and resolution and execution are separate. The imports are parsed and resolved first. By the time the code executes, all bindings are already resolved. – Joseph Commented Oct 25, 2016 at 13:05
- 2 the best practice is to not do this – The Reason Commented Oct 25, 2016 at 13:06
- 2 @TheReason Actually, importing your own module namespace object can be a useful thing that helps to avoid some duplicate code. – Bergi Commented Oct 25, 2016 at 14:14
- 1 @trusktr If you need to lookup things by name, you typically use an object literal with the respective values as properties. If those happen to be exactly your exports, you can just use the module namespace object. – Bergi Commented Apr 28, 2018 at 8:16
1 Answer
Reset to default 21Circular dependencies are no problem for declarative imports/exports. In your case, the circle is of minimal length though :-)
The solution is that an import
does not import a value into a variable, but that it makes a variable a reference to the exported variable. Have a look here for an example of a mutable variable, and at this question for exact terminology.
And it's the same for module namespace objects - their properties are just getters that resolve to the actual exported variable.
So when your module is loaded and evaluated, the following steps occur:
- The source is statically analysed for
export
andimport
declarations to build a dependency graph - The module scope is created
- Since the only dependency of your module is itself, and that already is getting initialised, it doesn't need to wait for it
- The
fooModule
variable is created and instantiated to an object with the exported names of the module, which are known to be["logFoo"]
. ThefooModule.logFoo
property becomes a getter that will evaluate to thelogFoo
variable in the module scope (if you had usedexport {A as B}
, thenfooModule.B
would resolve toA
, but in your case both names are the same). - The variable declarations in the module scope create the variables, in your case
logFoo
, and function declarations are initialised (i.e.logFoo
gets assigned the function) - The module code is run (in your case, nothing happens)
Now when you call logFoo
in a module that imports it, fooModule
will refer to the namespace that contains logFoo
. No magic :-)