1

Until today, I had not known the with operator existed. I stumbled upon it while debugging an issue being thrown from a plugin (Backbone.Epoxy).

The operator creates block level scope for each property on the passed object.

var testObj = { "cat":true };
with (testObj) {
  console.log(cat ? "Cat!": "dog"); // Cat!
}

Simple enough? Initially I thought this could potentially be really cool. Until I realized why my code was throwing an error. Here is an example derived from my code.

var testObj = { "css":true, "background-color":"blue" };
with (testObj) {
  console.log(css ? background-color : ""); // throws
}

The actual code is a bit more dynamic, but this is essentially what occurs behind the scenes in the plugin. Since dashes are not allowed within variable names but are allowed in property names, which cause the error to be thrown.

So, to the questions:

  1. Is there a way to sanitize the block scope local variable in order to avoid the issues with the dash while keeping it in my property name?
  2. Has anyone else worked around this issue with epoxy?
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Mad-Chemist
  • 487
  • 6
  • 18
  • 5
    You're best off [avoiding `with` altogther](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/with). More [information here](http://stackoverflow.com/questions/61552/are-there-legitimate-uses-for-javascripts-with-statement). – Andy Dec 08 '15 at 21:38
  • 2
    It’s the same with `window` properties. You can define `window['a-b'] = 4;` but couldn’t write `console.log(a-b);`. You could in some cases write `this['background-color']`. – Sebastian Simon Dec 08 '15 at 21:42
  • @Xufox Ooh! I hadn't thought of that issue, good catch. – Mad-Chemist Dec 08 '15 at 21:42
  • @Xufox `this` actually does not refer to the scope, except when the scope is coincidentally the root (or you've managed to abuse `with`). Try `(function(){console.log(this)})()` – mk. Dec 08 '15 at 21:45
  • @mk. Oh yeah, “always” was definitely wrong. I wasn’t paying attention when I wrote that… – Sebastian Simon Dec 08 '15 at 21:47

1 Answers1

3

You would have to make an exception and write:

testObj["background-color"]

As you may suspect, you cannot write just background-color, for the same reason you cannot write testObj.background-color. You should also ask whether using with, which is fairly non-standard, is worth the character-count savings. Usually the answer is "no".

mk.
  • 11,360
  • 6
  • 40
  • 54
  • The difficulty with our implementation is that the with operator is being used deep within a plugin. Generally, we try to avoid changing plugin source code. If this was something one of our developers had written, it would be easier to write around. I've currently posed the issue to the plugin's team: https://github.com/gmac/backbone.epoxy/issues/130 – Mad-Chemist Dec 08 '15 at 21:42
  • @Mad-Chemist the problem isn't that it's being made a block-level local variable, it's that you're subtracting `color` from `background`. It actually does exist at your newly-defined block scope, but you can't access it in the normal way - you have to do what I suggest in my answer instead. – mk. Dec 08 '15 at 21:47
  • @Mad-Chemist, what is that plugin you are using doing with that data you are passing into it? – CBroe Dec 08 '15 at 21:51
  • @CBroe I think I mentioned it above, but I'm using Backbone with the plugin (culprit) Backbone.Epoxy – Mad-Chemist Dec 08 '15 at 21:53
  • What’s that plugin doing with the object key `background-color` that you are passing in then? – CBroe Dec 08 '15 at 21:54
  • https://github.com/gmac/backbone.epoxy/blob/master/backbone.epoxy.js#L1265 They would have to re-write that. The best you can do is use `backgroundColor` instead - you have control over your own code, and generally it's bad practice to use dashes in your property names. – mk. Dec 08 '15 at 21:57
  • @mk. These properties are taken directly from CSS, and `background-color` is a valid CSS property. I would rather not modify it while ingesting and digesting the property. I've currently opened an issue with the plugin in hopes they are open to changing their code. – Mad-Chemist Dec 08 '15 at 22:08
  • @mk: Yeah, that is what I was getting at. @MadChemist, if you say that you are looking for a workaround so that you won’t have to modify the plugin, then `backgroundColor` should do, right? (Or the same syntax for every other(?) possible [CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference).) Since you already filed a report on the issue with them, give them time to fix it for a future release – and then remove the workaround at a later point, if convenient. – CBroe Dec 08 '15 at 22:15