That still happens.
It takes a lot of magic trickery to make cyclical require/imports work for JavaScript and a lot of times they don't/can't.
That still happens.
It takes a lot of magic trickery to make cyclical require/imports work for JavaScript and a lot of times they don't/can't.
Realistically, that's just what happens when a language allows top-level statements, as they are executed when a file is loaded. As such, scripting languages tend to fall victim to the problem, but compiled ones don't.
I'll update my comment.
So if you just need to call that binding within, say, a function or a method call, its typically fine to do so assuming that by the time that function or method call is executed, both modules will have completed their initializations.
const foo = require("foo"); // starts out as empty object
exports.bar = function() {
return foo.fn();
}let x = require('foo').x
of course, cannot do that. It's a small difference but it does make it easier to fall into the happy path in more cases.
Lots of languages allow initialization code (e.g. Java static initializer).
But in the case of scripting languages, usually the classes and functions themselves are initialization code....i.e. everything is initialization code.