Avoid global variables in JavaScript
Learn more about common concepts to organize code in a flexible way with Advanced Inertia.
One of the popular ways to share common pieces of data across multiple JavaScript modules is still heavy using the window
object.
However, there are several common reasons global variables are considered antipattern:
- It can be accessed from any other modules
- It can lead to name collisions with other libraries or methods
- It misses type-safety and direct IDE support
In the end, you can never be sure that the object you refer to is instantiated and even present on the window
object.
Take this example from a basic Laravel setup. It creates the Echo
data object on the window
object that carries an initialized instance of laravel-echo
.
import Echo from "laravel-echo"window.Echo = new Echo({broadcaster: "pusher",key: "..."})
We can access this object anywhere as long as the module containing this definition is imported somewhere in the app.
Echo.private("chat").listen(/* ... */)
Unfortunately, there’s no guarantee the Echo
instance is accessible, and the IDE also can’t help you with a hint unless you define global types manually.
So, here go singletons. Singleton is a pattern that lets you create object instances that are only resolved once on the first call.
Thanks to modern JavaScript, ES Modules are singletons by default. Singleton instances are created on the first access, so whenever you import a module, you are guaranteed to get the same instance from anywhere you import it.
Everything you need to make some class a singleton is to export its initializer.
import Echo from "laravel-echo"export default new Echo({broadcaster: "pusher",key: "..."})
Now, you can import it from any module or component, being confident that the instance is only resolved once and sharing its properties with all references.
import echo from "@/utils/echo"echo.private("chat").listen("MessageSent", (event) => {messages.push(event.message)})