Variable Variables in JavaScript: How to Reference Variables by Their String Names
Have you ever needed to access a variable by its name stored as a string? For example, if you have a variable userName and a string varName = "userName", could you use varName to get the value of userName? This concept—dynamically referencing variables via string names—is often called "variable variables."
While some languages like PHP support this natively (e.g., $$var), JavaScript does not have built-in syntax for variable variables. However, JavaScript offers several workarounds to achieve the same result. In this blog, we’ll explore these methods, their tradeoffs, best practices, and real-world use cases. By the end, you’ll know how to safely and effectively reference variables by string names in JavaScript.
Table of Contents#
- What Are Variable Variables?
- Why JavaScript Doesn’t Have Built-In Variable Variables
- Methods to Achieve Variable Variables in JavaScript
- Best Practices
- Use Cases
- Common Pitfalls
- Conclusion
- References
What Are Variable Variables?#
Variable variables (or dynamic variable names) allow you to reference a variable using a string that matches its identifier. For example, if you have:
const fruit = "apple";
const apple = "red";A "variable variable" feature would let you use fruit (which holds "apple") to access the value of apple (i.e., "red").
In languages like PHP, this is straightforward with the $$ syntax:
$fruit = "apple";
$apple = "red";
echo $$fruit; // Output: "red"JavaScript lacks this syntax, but we can replicate the behavior using other language features.
Why JavaScript Doesn’t Have Built-In Variable Variables#
JavaScript’s design prioritizes scoping and security, which makes native variable variables problematic:
- Scoping Complexity: Variables in JavaScript live in specific scopes (global, function, block). A native
$$-like feature would need to resolve variables across scopes, leading to ambiguity and bugs. - Security Risks: Dynamic variable access could expose sensitive data or execute malicious code if misused.
- Performance: Static variable access is optimized by JavaScript engines. Dynamic access would bypass these optimizations.
Instead, JavaScript encourages using objects or maps to manage dynamic values, which are safer and more predictable.
Methods to Achieve Variable Variables in JavaScript#
Let’s explore the most common ways to reference variables by string names in JavaScript, ranked by safety and recommendation level.
1. Using Objects (Recommended)#
The best approach is to store values as properties of an object, then access them using bracket notation with a string key. Objects act as "containers" for dynamic values, avoiding scoping issues and security risks.
How It Works:#
- Define an object where keys are "variable names" and values are the data you want to access.
- Use
object[stringKey]to dynamically retrieve the value.
Example:#
// Step 1: Store values in an object
const user = {
name: "Alice",
age: 30,
isAdmin: true
};
// Step 2: Define the string key (could be dynamic)
const key = "name";
// Step 3: Access the value using bracket notation
console.log(user[key]); // Output: "Alice"Dynamic Key Assignment:#
You can also dynamically assign values:
const config = {};
const settingName = "theme";
config[settingName] = "dark"; // Equivalent to config.theme = "dark"
console.log(config.theme); // Output: "dark"ES6 Maps: An Alternative to Objects#
For more advanced use cases (e.g., frequent additions/removals, non-string keys), use Map (ES6+):
const dynamicValues = new Map();
dynamicValues.set("greeting", "Hello");
dynamicValues.set("count", 42);
const key = "greeting";
console.log(dynamicValues.get(key)); // Output: "Hello"Maps are optimized for dynamic key-value pairs and avoid edge cases with object prototypes (e.g., toString or hasOwnProperty conflicts).
2. Using the window Object (Global Variables Only)#
In browsers, global variables (declared with var or undeclared) become properties of the window object. You can access them via window[stringKey].
⚠️ Warning: This only works for global variables and is strongly discouraged due to scoping and security issues.
Example:#
// Declare a global variable with `var` (creates a window property)
var globalVar = "I'm global";
// Access via window[stringKey]
const key = "globalVar";
console.log(window[key]); // Output: "I'm global"Limitations:#
- Not for Block/Function Scopes: Variables declared with
let/constin the global scope do not becomewindowproperties:let globalLet = "test"; console.log(window["globalLet"]); // Output: undefined (because `let` avoids window pollution) - Global Scope Pollution: Overusing global variables leads to naming collisions and bugs.
3. Using eval() (Discouraged)#
The eval() function executes a string as JavaScript code. While it can access variables dynamically, it is extremely risky and rarely necessary.
How It Works:#
const varName = "score";
const score = 95;
// Use eval() to execute "score" as code
console.log(eval(varName)); // Output: 95Why Avoid eval():#
- Security Risks: If
varNamecontains untrusted input (e.g., user input),eval()will execute it as code:const userInput = 'alert("Hacked!");'; eval(userInput); // Executes the alert! - Performance:
eval()bypasses JavaScript engine optimizations (e.g., JIT compilation). - Debugging Nightmares: Code executed by
eval()is hard to trace in debuggers.
Rule of Thumb: Never use eval() unless you fully control the input and there’s no alternative.
Comparison of Methods#
| Method | Scope | Security | Performance | recommendation level |
|---|---|---|---|---|
| Objects/Maps | Any (local/global) | Safe | Excellent | Highly Recommended |
window Object | Global only | Risky | Good | Not Recommended |
eval() | Any | Very Risky | Poor | Avoid |
Best Practices#
To use dynamic variable access safely and effectively:
- Prefer Objects/Maps Over
window/eval(): They limit scope, avoid global pollution, and are easier to debug. - Validate Keys: Check if a property exists before accessing it to avoid
undefinederrors:const data = { name: "Alice" }; const key = "age"; console.log(data[key] ?? "Key not found"); // Output: "Key not found" (using nullish coalescing) - Use
const/letfor Objects: Prevent accidental reassignment:const config = { theme: "light" }; // `config` can’t be reassigned, but properties can be modified - Avoid Global Variables: Even with
window, global variables are prone to collisions. Use modules or closures instead.
Use Cases#
Dynamic variable access is useful in scenarios like:
1. Dynamic Configuration#
Load configuration values based on environment or user input:
const env = "production";
const config = {
development: { apiUrl: "http://localhost:3000" },
production: { apiUrl: "https://api.example.com" }
};
const currentConfig = config[env]; // Uses `env` string to pick the right config2. Form Data Handling#
Map form input names to values dynamically:
// HTML: <input name="email" value="[email protected]">
// <input name="password" value="secure123">
const formData = {};
document.querySelectorAll("input").forEach(input => {
const fieldName = input.name; // e.g., "email" or "password"
formData[fieldName] = input.value;
});
console.log(formData.email); // Output: "[email protected]"3. Dynamic Module Loading#
Load modules based on a string (e.g., in a router):
const routes = {
home: () => import("./pages/home.js"),
about: () => import("./pages/about.js")
};
const page = "home";
routes[page]().then(module => module.render()); // Loads the "home" page moduleCommon Pitfalls#
Watch out for these mistakes when using dynamic variable access:
1. Assuming let/const Global Variables Are window Properties#
Only var and undeclared variables become window properties. let/const in the global scope do not:
let globalLet = "test";
console.log(window["globalLet"]); // undefined (use an object instead!)2. Forgetting Bracket Notation#
Dot notation does not work with dynamic keys. Always use brackets for string keys:
const obj = { price: 10 };
const key = "price";
console.log(obj.key); // undefined (dot notation looks for a property named "key")
console.log(obj[key]); // 10 (correct)3. Overusing Dynamic Access#
Static access is faster and clearer. Use dynamic access only when the key is truly unknown until runtime.
Conclusion#
While JavaScript lacks native variable variables, you can achieve the same result safely using objects or maps. This approach avoids the security and scoping issues of window or eval(), making your code more maintainable and robust.
Remember: Objects are your friends for dynamic values. Reserve window and eval() for rare edge cases, and always validate dynamic keys to avoid bugs.