8

What I tried (which works in chrome)

var class_str = "class Test {};";
var a = eval(class_str);
console.log(new a());

Raises following error in Firefox 46:

TypeError: a is not a constructor

a is undefined and using new A() returns ReferenceError: A is not defined.

What is different on Firefox?

5
  • just what is returned from eval. try var class_str = "class Test {}; return Test;"; Commented Sep 2, 2016 at 18:53
  • It returns SyntaxError: return not in function @DanielA.White Chrome does not work that way, too. Commented Sep 2, 2016 at 18:56
  • If you type class Test {}; into the console, you'll see that Firefox gives you undefined, while Chrome gives you the class. So Chrome is providing a value for the last statement in the program, while Firefox isn't. Not sure which is correct. Another example of a statement returning a value would be to see the result of a for statement using eval. var x = eval("for (var i = 0; i < 10; i++) { i }"); console.log(x); // 9 Commented Sep 2, 2016 at 18:57
  • @squint Thanks, it turns out I just need to put the whole class in parentheses, as in (class Test {}) Commented Sep 2, 2016 at 19:09
  • Possible duplicate of Using eval to execute functions or How to convert text to a function using JavaScript Commented Sep 2, 2016 at 19:36

2 Answers 2

14

Putting the whole class string in parentheses works.

Fixed code:

var class_str = "(class Test {})";
var a = eval(class_str);
console.log(new a());
Sign up to request clarification or add additional context in comments.

6 Comments

Taking a quick look at the spec, it seems like Firefox may be correct. It looks like there's a distinction between a class declaration and expression, much like functions, and the Return of each seems to mirror that of functions, so wrapping in parens would have the same effect of making it an expression.
@Oriol: Yeah, I saw that too, but then I looked at the next section 14.5.16 Runtime Semantics: Evaluation, under ClassDeclaration : class BindingIdentifier ClassTail which calls the section you referenced, and it shows Return NormalCompletion(empty), just like function declarations do. However I'm totally guessing at what NormalCompletion(empty) actually means, so I could be wrong.
I think the closest I can find for now is 6 ECMAScript Data Types and Values, which states "...When the term “empty” is used as if it was naming a value, it is equivalent to saying “no value of any type”.". Don't know if that's the right section or not, or if "no value of any type" translate to the Undefined type eventually.
@squint You are right, of course. Declarations don't return values, just like statements. They return completions. NormalCompletion means that the code finished without return, break, etc., and empty means no value, which eval will transform to undefined.
@Oriol: So because the completion has a value, and the value is given empty, it must translate to undefined, but that's an assumption on my part. I'll check out eval quick to see if that's the case.
|
2

I tried another method that works just as using parentheses and seems much simpler as it doesn't pollute global names.

result = eval(`class a{} window.a=a`)

console.log(result)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.