| technology | JavaScript | ||||
|---|---|---|---|---|---|
| domain | frontend | ||||
| level | Senior/Architect | ||||
| version | ES2022+ | ||||
| tags |
|
||||
| ai_role | Senior JavaScript Expert | ||||
| last_updated | 2026-04-05 |
Note
Context: Scoping and hoisting mechanisms in modern JavaScript. var is function-scoped and hoisted, leading to unpredictable behavior and accidental global leakage.
var price = 100;
if (true) {
var price = 200; // Overwrites outer variable
}
console.log(price); // 200var does not respect block scope. Its hoisting behavior allows variables to be accessed before declaration (as undefined), which bypasses the Temporal Dead Zone (TDZ) safety mechanism, increasing cognitive load and bug density.
const price = 100;
if (true) {
const price = 200; // Block-scoped, unique to this block
}
console.log(price); // 100Use const by default to ensure immutability of the reference. Use let only when reassigning a variable is strictly necessary. This enforces block-level scoping and prevents accidental overrides.
flowchart TD
A[Variable Declaration Required] --> B{Reassignment needed?}
B -->|Yes| C[Use let]
B -->|No| D[Use const]
C --> E[Block Scoped Variable]
D --> E
classDef default fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px,color:#000;
classDef component fill:#e8f5e9,stroke:#4caf50,stroke-width:2px,color:#000;
class A,C,D default;
class B,E component;
Note
Context: JavaScript's type coercion rules are complex and often counter-intuitive.
if (userCount == '0') {
// Executes if userCount is 0 (number) or '0' (string)
}The Abstract Equality Comparison Algorithm (==) performs implicit type conversion. This leads to edge cases like [] == ![] being true or 0 == '' being true, which can cause silent logic failures.
if (userCount === 0) {
// Strict comparison
}Always use strict equality === and inequality !==. This forces the developer to handle type conversions explicitly, making the code's intent clear and predictable.
Note
Context: The global namespace is shared. Overwriting global properties can break third-party libraries or browser APIs.
// In a script file
const config = { api: '/v1' };
function init() { /* ... */ }Variables declared in the top-level scope of a non-module script are attached to window (in browsers) or global (in Node). This increases the risk of name collisions and memory leaks.
// use modules
export const config = { api: '/v1' };
// or IIFE if modules aren't available
(() => {
const config = { api: '/v1' };
})();Use ES Modules (import/export) to encapsulate code. Modules have their own scope and do not leak to the global object.
Note
Context: Readability and handling of multi-line strings/expressions.
const greeting = 'Hello, ' + user.firstName + ' ' + user.lastName + '! ' +
'Welcome to ' + siteName + '.';Concatenation with + is error-prone, hard to read, and difficult to maintain for multi-line strings. It often leads to missing spaces and poor visual structure.
const greeting = `Hello, ${user.firstName} ${user.lastName}!
Welcome to ${siteName}.`;Use Template Literals (backticks). They allow for embedded expressions, multi-line strings, and superior readability.
Note
Context: Numbers with no context make the codebase hard to maintain.
if (user.age >= 18) {
grantAccess();
}"18" is a magic number. If the legal age changes, you must find and replace every instance, risking errors if the same number is used for different contexts elsewhere.
const LEGAL_AGE = 18;
if (user.age >= LEGAL_AGE) {
grantAccess();
}