Note: This isn't a question about best practices. The with
statement is obviously something we should avoid in regular JS usage. I'm interested in its behaviour because I'm writing a simple DSL and seeing how I can push JavaScript's limits to make certain features work.
Consider the following code:
var obj = {prop:0};
with(obj) { prop = 1; }
// obj.prop === 1
Whenever we use a variable inside the with
block (like prop
, above), it first looks to see if that variable is a property of obj
. If it is, then it basically converts that variable to obj.prop
.
However, if the variable is not found within obj
, then the JS engine surfs up the scope chain looking for prop
until it reaches the global object as a last resort:
var obj = {};
with(obj) { prop = 1; }
// obj.prop === undefined
// window.prop === 1
Here's my question: In the above example, the JS engine looks for prop
within obj
. Is there a way to intercept this lookup? I'd like to "trick" the JS engine (in a spec-compliant way, of course) into thinking that obj
has every property in existence, so that all variables references withing the with
statement are interpreted as obj.variable
. Basically, I want this behaviour:
var obj = {};
with(obj) { prop = 1; }
// obj.prop === 1
I thought this would be as simple as proxying obj
and intercepting get
s, since (I figured) the engine would do a get
to see is obj
has prop
. I thought that I could simply return something other than undefined
, and then the with
would treat obj
as having all properties:
var prox = new Proxy({}, {
set(target, property, value) { target[property] = value; },
get(target, property) { return target[property] !== undefined ? target[property] : null; },
});
with(prox) { prop = 1; }
But that doesn't seem to work. Any ideas?