Underlying Principles of JavaScript Variable System
Variable Storage Mechanism
JavaScript variables are managed at the low level through variable environments and lexical environments, which form the foundation of JavaScript’s scope system. Internally, variables are stored in specific data structures, with the exact implementation varying depending on the JavaScript engine (e.g., V8, SpiderMonkey).
Basic Structure of Variable Storage:
- Global Variables: Stored as properties of the global object (
windowin browsers,globalin Node.js). - Local Variables: Stored in the function call stack’s frame.
- Closure Variables: Stored in a specialized closure data structure.
// Global variable example
var globalVar = 'I am global'; // Stored in the global object
function test() {
// Local variable example
var localVar = 'I am local'; // Stored in the function call stack's frame
if (true) {
// Block-scoped variable (ES6 let/const)
let blockVar = 'I am block scoped'; // Stored in the lexical environment
}
}Variable Declaration and Hoisting
JavaScript variable declarations are “hoisted” to the top of their scope during the compilation phase, but their initialization remains in place. This behavior is handled by the JavaScript engine before code execution.
Hoisting with var Declarations:
console.log(a); // undefined (no error, variable is declared but not initialized)
var a = 10;Internally equivalent to:
var a; // Declaration hoisted
console.log(a); // undefined
a = 10; // Initialization stays in placeHoisting with let/const Declarations (Temporal Dead Zone):
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;Although let and const are hoisted, they reside in a Temporal Dead Zone (TDZ), causing a ReferenceError if accessed before their declaration.
Variable Types and Memory Allocation
Memory allocation for JavaScript variables depends on their type:
- Primitive Types:
- Stored in stack memory.
- Includes:
string,number,boolean,null,undefined,symbol,bigint. - Stores the value directly.
- Reference Types:
- Stored in heap memory.
- Includes:
object,array,function,date, etc. - Stack stores a reference address pointing to the heap.
// Primitive type example
let num = 42; // Stored in stack
let str = 'hello'; // Stored in stack
// Reference type example
let obj = { a: 1 }; // Object stored in heap, obj holds reference to heap
let arr = [1, 2, 3]; // Array stored in heap, arr holds reference to heapVariable Scope and Closures
Scope Chain is the mechanism JavaScript uses to resolve variable lookups, consisting of the current execution environment and all parent execution environments’ variable objects.
Closure is a combination of a function and its surrounding state (lexical environment), allowing the function to access variables outside its lexical scope.
function outer() {
let outerVar = 'I am outer'; // Stored in outer's lexical environment
function inner() {
console.log(outerVar); // Accesses outer variable, forming a closure
}
return inner;
}
const closureFunc = outer();
closureFunc(); // Output: "I am outer"At the low level, a closure maintains a reference to its lexical environment, even after the outer function has finished executing.
Underlying Principles of JavaScript Functions
Function Definition and Storage
JavaScript functions are special objects with the following characteristics:
- Instances of the
Functionobject. - Can have properties and methods like regular objects.
- Can be invoked for execution.
Low-Level Representation of Function Creation:
function greet(name) {
return `Hello, ${name}!`;
}Internally equivalent to:
const greet = new Function('name', 'return `Hello, ${name}!`;');Function Call Mechanism
A function call involves the following steps:
- Create an execution context.
- Create a variable environment.
- Establish the scope chain.
- Determine
thisbinding. - Execute the function body.
- Return the result (or implicitly return
undefined).
Low-Level Process of a Function Call:
function add(a, b) {
return a + b;
}
add(2, 3);Internally equivalent to:
- Create a new execution context.
- Bind parameters
aandbto the execution context’s variable environment. - Execute the function body
return a + b. - Return the result
5. - Destroy the execution context (subject to garbage collection).
this Binding Mechanism
The binding of this in JavaScript is complex and depends on how a function is called:
- Default Binding: Independent function call,
thispoints to the global object (non-strict mode) orundefined(strict mode). - Implicit Binding: Called as an object method,
thispoints to the calling object. - Explicit Binding: Using
call,apply, orbind,thispoints to the specified object. - New Binding: Called with
newas a constructor,thispoints to the newly created object. - Arrow Functions:
thisis inherited from the enclosing scope.
// Default binding
function defaultBind() {
console.log(this); // Browser: window, Node.js: global
}
defaultBind();
// Implicit binding
const obj = {
method: function() {
console.log(this); // obj
}
};
obj.method();
// Explicit binding
function explicitBind() {
console.log(this); // Specified object
}
explicitBind.call({ custom: 'object' });
// New binding
function Person(name) {
this.name = name;
}
const p = new Person('John');
console.log(p.name); // John
// Arrow function
const arrowFunc = () => {
console.log(this); // Inherited from outer scope
};Function Parameter Handling
JavaScript function parameters have the following characteristics:
- Flexible number of parameters (supports variadic functions).
- Parameters are passed by value (for objects, passed by sharing).
- Supports default parameters.
- Supports rest parameters.
Low-Level Implementation of Parameter Handling:
function example(a, b = 10, ...rest) {
console.log(a, b, rest);
}
example(1, 2, 3, 4, 5);Internally equivalent to:
function example(a, b, rest) {
// Default parameter handling
if (b === undefined) {
b = 10;
}
// Rest parameter handling
if (arguments.length > 2) {
rest = Array.prototype.slice.call(arguments, 2);
} else {
rest = [];
}
console.log(a, b, rest);
}
example(1, 2, 3, 4, 5);Function Hoisting and Function Expressions
Function declarations are hoisted, while function expressions are not:
// Function declaration (hoisted)
foo(); // "I am a function"
function foo() {
console.log("I am a function");
}
// Function expression (not hoisted)
bar(); // TypeError: bar is not a function
var bar = function() {
console.log("I am a function expression");
};Low-Level Difference:
- Function declarations are processed and added to the scope during compilation.
- Function expressions are assigned during runtime.



