views:

66

answers:

3

Is it possible to access object properties that can only be accessed with the square bracket notation when inside a "with" statement.

Example:

var o = { "bad-property": 1, "another:bad:property": 2, "goodProperty": 3 };

with(o) {
    console.log(goodProperty); // works awesome
    console.log(???) // how to access "bad:property"?
}
A: 

As I understand it with(o) essentially jumps to the scope of o, so properties are accessible by their name: “bad” and “goodProperty” respectively.

with(o) {
  bad="new value";
  goodProperty=22;
}
The question was, how to access properties that are inaccessible by their name (by virtue of how they were named).
Lauri Lehtinen
I added a confusing property name. `"bad:property"` is the name of the property (it could've just as well been `"bad-property"`), but I don't know if it's accessible inside the with scope. One solution is to normalize the property name and change `"bad:property"` to `"badProperty"`, but I was hoping to avoid that as it may be impossible for some cases.
Anurag
+1  A: 

Generally the with keyword is used to resolve long namespaces, not a single object reference. I guess I'd need to know what the intent of using the keyword here is. I don't believe the syntax parser will let you get away with o.bad:property, which is basically what's being coded using with.

If the o object in the example was just a shortcut to a longer namespace, my recommendation would be to stop one object short in the resolution using with, then put box your property into a string like this...

var nmSpace = new Object();
nmSpace.o = { "bad:property": 1, "goodProperty": 2 };

with (nmSpace) {
    alert(o['goodProperty']); // works awesome
    alert(o['bad:property']);  // now accesses "bad:property"!
}

Hope that helps.

Laramie
It's being used in a template using [JR's tiny library](http://ejohn.org/blog/javascript-micro-templating/). The data is coming from an external source, and I am passing the relevant root object to the template engine which populates it. I can't arbitrarily break object chains without also breaking apart the templates.
Anurag
got it. if you can't influence the template to string qualify the property names, my guess is that you're on the money with having to normalize property names through regex to avoid syntax violations.
Laramie
The only way to access those values would be through quoted identifiers -- o['bad-property'] and o['bad:property'] still work. This works inside the `with` (though at this point you shouldn't need to use it). And the props are still available through `for(var s in o){}. If your templating engine is expecting a variable name exactly matching the property name of your object, I don't think you can do it without, as you already mentioned, normalizing everything.
Andrew
thanks @Laramie - that's what I am doing as of now as there seems to be no other alternative. @Andrew - I would lose all benefits of using the templates if `o` is directly referenced, unless I wrap everything inside another object (for consistency) just to be able to access them as `outerObject['x:prop']` as @Laramie suggested, but I'll let that go for now.
Anurag
+1  A: 

Wow this is old, but the answers here are wrong, there is in fact way to do exactly as you ask.

with({'!@#$%': 'omg', d: 'hai'}) {
  console.log(d); //hai - naturally
  console.log(valueOf()['!@#$%']); //omg - OMG
}

Did you see it? valueOf() is the magic word. It returns the primitive value of its parent object, or if the object has no primitive value, the object itself. Every object and object-like primitive inherits this method, as it is a built in property on Object.prototype. So...there you go.

MooGoo