mjs
mjs

Reputation: 22357

How efficient is the "with" statement?

It is hard to Google for some keywords like "with" word, so I am testing to ask here.

Is the with statement in JavaScript inefficient?

For instance, say I have:

with(obj3) {
     with(obj2) {
         with(obj1) {
               with(obj0) {
                    eval("(function() { console.log(aproperty) })();");
               }
         }
     }
}

Would the above be more or less efficient, if for instance, I walked over obj0, obj1, obj2, obj3 and merged them together, and then used either:

  1. One with statement alone
  2. Created a parameters string with the keys of obj0, obj1, obj2 and obj3, and an args array for the values and used:

    eval("function fn(aproperty, bproperty) { console.log(aproperty); }")
    fn.apply(undefined, args);
    

Which of these three approaches can be deemed to be quicker? I am guessing on with statements but so many with's makes me think I can optimize it further.

Upvotes: 3

Views: 147

Answers (3)

Blue Skies
Blue Skies

Reputation: 2975

If you're looking for options, then you may want to consider a third approach, which would be to create (on the fly if needed) a prototype chain of objects.


EDIT: My solution was broken. It requres the non-standard __proto__ property. I'm updating to fix it, but be aware that this isn't supported in all environments.


var objs = [null,obj3,obj2,obj1,obj0];

for (var i = 1; i < objs.length; i++) {
    objs[i].__proto__ = Object.create(objs[i-1]);
}

var result = objs.pop();

This avoids with and should be quicker than merging, though only testing will tell.


And then if all you needed was a product of certain properties, this will be very quick.

var props = ["x2","b1","a3"];
var product = result.y3;

for (var i = 0; i < props.length; i++)
    product *= result[props[i]];

Upvotes: 2

Esailija
Esailija

Reputation: 140220

With statement will make your code run like it's 1980 - literally every optimization implemented in a JIT cannot be used when it's in effect.

Upvotes: 0

peterh
peterh

Reputation: 1

Newer browsers have an internal tokening mechanism to make the javascript interpretation cheaper. It is very like JIT in the newer JVMs. I think there isn't a much problem with your deeply embedded with-s, practically it will be some like

__get_aproperty() {
    if (obj0.has("aproperty")) return obj0.aproperty;
    if (obj1.has("aproperty")) return obj1.aproperty;
    if (obj2.has("aproperty")) return obj2.aproperty;
    if (obj3.has("aproperty")) return obj3.aproperty;
}

So, the structure of your js is highly embedded, but the structure of the real execution in the JS-engine of the browsers, will be simple and linear.

But the tokenization of the JS, that is costly. And if the JS-engine finds an eval, needs to tokenize.

I voted for the first version.

Upvotes: 1

Related Questions