1

The following JavaScript...

if (eval('typeof admin_post_css_theme_dark-moon)=='function')) {/**/}

...triggers the following error message...

Error: ReferenceError: moon is not defined

The only thing I can really differentiate in this situation is that other themes don't have a dash in their names...

if (eval('typeof admin_post_css_theme_silver)=='function')) {/**/}

...doesn't trigger any errors.

So how is the dash between 'dark' and 'moon' triggering this error?


Edit: I wanted to take a moment and recommend that others who encounter this should adapt camelCase or something similar. In general I use a 'name' and a 'base' myself. The 'base' is the URL-friendly version of something that the 'name' includes URL unfriendly characters. In example 'My Example' and 'my-example' or 'my_example'.

http://en.wikipedia.org/wiki/CamelCase

John
  • 1
  • 13
  • 98
  • 177
  • Why are you using eval? Is there no way to do this without it? – random_user_name Mar 20 '14 at 21:36
  • I *must* use `eval`, this is *not* an `eval` debate question. – John Mar 20 '14 at 21:37
  • 5
    Your sample is broken. I get *SyntaxError: Unexpected token function*. In any case `admin_post_css_theme_dark-moon` isn't a valid identifier. The hyphen would be interpretted as a subtraction operator. – p.s.w.g Mar 20 '14 at 21:37
  • - is asking the javascript runtime to subtract the variable 'moon' from the variable 'admin_post_css_them_dark'. cale_b was trying to help when he asked about eval because if you try to eval with a - in the expression, the runtime is going to try to subtract the two variables. – Dave Bush Mar 20 '14 at 21:40
  • Try the eval content on browser console first. – palanik Mar 20 '14 at 21:45
  • Yeah I tried it in the console. Turns out I needed to throw in a couple escaped single quotes. Answer is below, other two by OJay and sabof helped. – John Mar 20 '14 at 21:47
  • 3
    @John It looks like you're generating the function name dynamically? If so, you can still avoid `eval`, by using a hash lookup - for example: `typeof window['admin_post_css_theme_dark' + '_' + 'moon'] == 'function'` – Izkata Mar 20 '14 at 21:53
  • Does this answer your question? [How do I reference a javascript object property with a hyphen in it?](https://stackoverflow.com/questions/7122609/how-do-i-reference-a-javascript-object-property-with-a-hyphen-in-it) – Henke Jan 29 '21 at 10:41
  • @Henke No, that is a jQuery question, mine is JavaScript. – John Jan 29 '21 at 11:17

3 Answers3

6

JavaScript variable names can't contain dashes, object properties however can. For instance, something like this would work:

var themes = {
  'admin_post_css_theme_dark-moon': function () {},
  'admin_post_css_theme_silver': function () {}
};

if (typeof themes['admin_post_css_theme_dark-moon'] === 'function') {
  /**/
}
sabof
  • 8,062
  • 4
  • 28
  • 52
  • Close but to zero-in on the problem I was keeping the code concise. I'll post my answer but I'm still up-voting because you gave me the idea. Thanks! – John Mar 20 '14 at 21:44
5

Primarily because '-' is not a valid identifier in javascript, its the minus sign. Your eval in essence is trying to get the typeof the expression admin_post_css_theme_dark minus moon. Valid identifiers (i.e. variable, function or object names) in javascript are [A-Za-z0-9_$] but cannot start with a number (note this is a regex, and the hyphens in this context mean range i.e. a to z, just in case it was unclear)

My evolution to the question would be how would you have expected admin_post_css_theme_dark-moon to be defined, as you are expected it to be somehow/where in code, then in turn to test if it is a function.

As it would be absolutely impossible to do this

var admin_post_css_theme_dark-moon = function(){...};

//or

admin_post_css_theme_dark-moon = function(){...};

however it is possible to do this.

window['admin_post_css_theme_dark-moon'] = function(){...};

or preferably use your own object

var Themes = {};
Themes['admin_post_css_theme_dark-moon'] = function(){...};

//or

var Themes = {
    'admin_post_css_theme_dark-moon' : function(){...};
}

As object properties if referenced by string index (i.e. between [] as a string) are not bound by the identifier rules.

then of course your eval would have to change also

something like

if (eval("typeof window['admin_post_css_theme_dark-moon']")=='function')) {/**/}

//or

if (eval("typeof Themes['admin_post_css_theme_dark-moon']")=='function')) {/**/}

NOTE the use of alternating " and ' so you don't have to escape

OJay
  • 4,763
  • 3
  • 26
  • 47
-1

I changed...

eval('typeof '+my_object)=='function')

...to...

eval('typeof \''+my_object+'\'')=='function')

I didn't have the chance to edit this in so the question could be more concise. For those looking at just this answer check out the other answers from OJay and sabof as they are wholly relevant.

John
  • 1
  • 13
  • 98
  • 177
  • 1
    This won't throw an error, but the `typeof` will always be `"string"` – sabof Mar 20 '14 at 21:54
  • 2
    I don't think this will do what you expect it to. Most likely, it would return false, e.g. if `my_object` is a function like `alert`, `eval('typeof \''+my_obejct+'\'')` would return `"string"`, even though its a function. However if `my_object` evaluates to a string with a `'` it could dramatically change the behavior of the the eval, e.g. if `my_object` is a string like `"','function"`, `eval('typeof \''+my_obejct+'\'')` will return `"function"` even though `my_object` is a string. – p.s.w.g Mar 20 '14 at 22:00