2

It seems not possible to create a variable using eval in Node.js ES6 but I can't understand why. This happens to me on CentOS 7, but I don't believe OS is the problem here.

Regular Node.js file (test.js):

eval("var a=1");
console.log(a);

Make the same file with .mjs extension to run with Node.js ES6 (test.mjs):

eval("var a=1");
console.log(a);

After that, run the 2 files with Node.js, and Node.js ES6:

$ node test.js
1

$ node --experimental-modules test.mjs
(node:9966) ExperimentalWarning: The ESM module loader is experimental.
ReferenceError: a is not defined
    at file:///temp/test.mjs:2:13
    at ModuleJob.run (internal/modules/esm/module_job.js:96:12)

Is it an issue related to ES6? I tried on browser's console and the problem is the same:

>> eval("var a=1"); console.log(a);
   1

>> class c { static f(){ eval("var a=1"); console.log(a); } }
   c.f()
   ReferenceError: a is not defined

I'm using Node.js 10.9.0, is it a bug or there's a reason behind it?

Dee
  • 7,455
  • 6
  • 36
  • 70

2 Answers2

8

In strict mode, variables created inside an eval() statement are available only to that code. It does not create new variables in your local scope (here's a good article on the topic) whereas it can create variables in the local scope when not in strict mode.

And, mjs modules run in strict mode by default. A regular node.js script file is not in strict mode by default. So, the difference in strict mode setting causes a difference in behavior of eval().

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • @Barmar - Yes, I was confirming that before writing it, and have now added it to my answer. – jfriend00 Sep 04 '18 at 07:09
  • ic, mjs and browser es6 run in strict mode by default, and variables created in eval in strict mode won't be available outside, tks – Dee Sep 04 '18 at 07:15
  • @jfriend00, any workaround to create variable in local scope? i can't think of anything else rather than eval, but i must use es6 class. – Dee Sep 04 '18 at 11:13
  • 1
    @datdinhquoc - You'd have to show us what real coding problem you're actually trying to solve. Usually, the solution is to not actually create local variables, but to create a base object and then dynamically add properties to that object. That can be done with normal Javascript, even in strict mode. – jfriend00 Sep 04 '18 at 20:40
  • @jfriend00, tks, i'm now using the object.property solution, adding properties to object. eval to create variables is evil sometimes, it may break code if the being created variable is already in the code – Dee Sep 05 '18 at 05:26
1

With the answer from @jfriend00 and from my testing:

Calling eval directly doesn't work in es6 class or .mjs file:

eval("var a=1");
console.log(a);

However, calling eval INDIRECTLY does work in es6 class or .mjs file:

var geval = eval;
geval("var a=1");
console.log(a);
Dee
  • 7,455
  • 6
  • 36
  • 70