Why JavaScript’s with Statement Can Leak Data and Slow Down Your Code
This article explains how the JavaScript with statement creates a new lexical scope that can unintentionally create global variables, cause data leakage, and dramatically degrade performance, while also covering LHS/RHS lookup, execution contexts, variable/activation objects, and scope chain mechanics.
1. Background
During a casual conversation the author wondered why the
withstatement is considered problematic, and traced its origins through VO (Variable Object) and AO (Activation Object) to understand its behavior.
2. with
The
withstatement provides a namespace‑like access to an object's properties, allowing direct reference without the object prefix.
<code>const o = { a: 1, b: 2 };
with (o) {
console.log(a); // 1
b = 3; // o: { a: 1, b: 3 }
}
</code>It looks convenient, but nesting
withcan lead to scope‑chain side effects.
<code>const o = { a: 1, b: 2 };
const p = { a: 3 };
with (o) {
console.log(a); // 1
with (p) {
console.log(a); // 3
b = 4; // o: { a: 1, b: 4 }
c = 5; // window.c = 5
}
}
</code>If a property does not exist, the assignment follows the scope chain and, in non‑strict mode, creates an implicit global variable, leading to data leakage.
The failure to find a variable during an LHS lookup results in an implicit global (or a
ReferenceErrorin strict mode), whereas a failed RHS lookup throws a
ReferenceErrorimmediately.
2.1 Performance issue
Using
withprevents the engine from optimizing property access because it introduces a new lexical environment.
<code>function f () {
const o = { a: 1 };
console.time();
with (o) {
for (let i = 0; i < 100000; i++) {
a = 2;
}
}
console.timeEnd();
}
</code>Benchmark results (image omitted) show a nearly ten‑fold slowdown compared to the direct property access version:
<code>function f () {
const o = { a: 1 };
console.time();
for (let i = 0; i < 100000; i++) {
o.a = 2;
}
console.timeEnd();
}
</code>The reason is that the pre‑compilation phase cannot optimize the property lookup when
withcreates a separate lexical scope, forcing the engine to resolve identifiers at runtime.
3. LHS and RHS
LHS (Left‑Hand Side) is the target of an assignment.
RHS (Right‑Hand Side) is the source value of an assignment.
Example:
<code>var a = 1;
</code>The code is split into declaration and assignment:
<code>var a;
a = 1;
</code>When accessing
a, a RHS lookup obtains its value, while an LHS lookup determines where to store a new value. A failed RHS throws
ReferenceError; a failed LHS creates an implicit global (non‑strict) or also throws in strict mode.
4. Execution context and scope chain
JavaScript has three execution environments: global, function, and eval. Each execution context (EC) has a Variable Object (VO), a scope chain, and a
thisbinding, forming an Execution Context Stack (ECS).
4.1 VO
The Variable Object stores variables, function declarations, and parameters. In the global EC,
VO === this === global.
4.2 AO
In a function EC, the Activation Object (AO) replaces the VO; they are identical (
VO === AO).
<code>function foo(b) {
const a = 1;
}
foo(1);
// AO: { arguments: {...}, a: 1, b: 1 }
</code>4.3 Scope chain
The scope chain links the current VO/AO with all parent VOs/AOs, enabling identifier resolution.
<code>var x = 10;
function foo() {
var y = 20;
function bar() {
var z = 30;
console.log(x + y + z);
}
bar();
}
foo();
</code>Diagram (image omitted) shows orange arrows pointing to VO/AO and blue arrows representing the scope chain.
Understanding the scope chain makes it easy to relate to JavaScript’s prototype chain; together they form a two‑dimensional lookup: first locate an object via the scope chain, then locate a property via the prototype chain.
<code>const foo = {};
function bar() {
Object.prototype.a = 'Set foo.a from prototype';
return function () {
console.log(foo.a);
};
}
bar()(); // Set foo.a from prototype
</code>Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.