'How to share functions and variables between one Javascript file that IS a module, and another Javascript file that is NOT a module
I have a project built using Javascript, jQuery, and Vite.js. I need to share functions and variables between one JS file that is a module, and another JS file that is not a module. I'm specifically talking about whether the script tag has type="module"
or not. Is this possible? I understand that if I could just set both script file types to "module", this would solve my problem and I could easily just use import/export syntax to share functions and variables. However, the 2nd script cannot be set to type="module"
, as that would break snippets of code using certain dependencies.
Just to illustrate what I'm saying -- here's an HTML file linked to two different JS files:
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="module" src="./script1"></script>
<script src="./script2"></script>
</head>
<body></body>
</html>
Now, script1.js
has a variable we want to access from script2.js
:
script1.JS
const testVariable = "hello test variable";
script2.js
console.log(testVariable) //returns undefined
Obviously I can't use import/export or require since the 2nd script is not a module. Is there any way around this? I know that normally script files can access functions from script tags placed above them, but this doesn't seem to hold true for two different script types.
I thought maybe I could use jQuery $.getScript
per this S/O post, but as far as I can tell, that executes the requested script, but doesn't allow me to dynamically access specific variables and/or functions in the requested script?
Solution 1:[1]
Script modules do not implicitly create global variables. Variable, or named class or function names declared in a module are held in a closure created for module content, making them inaccessible by direct means from outside the module.
Global Variable Usage
If the only issue is not being able to access variables exported by a module script, consider creating the variables as properties of the global window
object in the module file instead of using variable declarations.
This would change module declarations like
let brandName = "fooware";
to
window.brandName = "fooware";
This would then allow code in any script to access brandName
as a variable.
Setters and Getters
If a script module is to remain unchanged, you could set up an intermediate module to import exported items and republish them as setters and getters of a global object property name, using Object.defineProperty* E.G.
<script type="module">
import {brandName} from "./script1.js";
Object.defineProperty(window, "brandName", {
get() { return brandName; },
set(newValue) { brandName = newValue; },
enumerable: true
});
</script>
Note this kind of module (which doens't export any values) can be included inline in HTML using <script> tags without a src
attribute.
*Object.defineProperties
can be used to define multiple accessor properties at a time using slightly different syntax.
Deferring the non-modular script
Module scripts are deferred automatically without requiring the browser to load and parse then synchronously. Try adding a defer
attribute to the non-modular script so it is executed in the same order as module script tags provided in page source. When deferred, the script will not be parsed before body HTML has been parsed.
Summary
JavaScript Modules are not designed to interact with non module script files. Refactoring non modular scripts into modules is generally preferred over more intrusive solutions.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |