Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReferenceError on Google Chrome but not on Firefox (Browser Bug?)

This piece of code

eval(`
    let a = 0;
    function f() {}
    function g() { a; }
    console.log(f);
`);

works fine on Firefox 48.0 while causing Uncaught ReferenceError: f is not defined on Google Chrome 52.0.2743.116 (64-bit).

It also works fine on Google Chrome if

  • eval is not used, or
  • the code inside eval is surround with {}, or
  • a is not referenced in g, or
  • let is changed to var, or
  • "use strict" is added before the code

What's happening here?

like image 563
johnchen902 Avatar asked Aug 12 '16 15:08

johnchen902


People also ask

What does Firefox have that Chrome doesn t?

Firefox Uses Less Memory Than Chrome Chrome creates extra processes for each page you open, each page has its own memory and its own copy. Instead, Firefox uses four content processes at any given time. Meaning that if you have 20 open tabs in Chrome, Chrome will use 20 processes and Firefox will only use four.

Why has Firefox stopped working?

If Firefox previously worked but suddenly doesn't start, it may be due to some corrupt data in your settings. Uninstalling and reinstalling Firefox would not fix this problem because your settings are not removed on uninstall. To test to see if this is the problem, use the Profile Manager to create a new profile.

Is Firefox still better than Chrome?

If you're looking for the best browser for Android, the two are great options. Chrome is a faster and more full-featured browser for everyday use, but many will prefer Firefox for its privacy and security.

Why you should switch from Chrome to Firefox?

Switching from Google Chrome to Firefox is easy and risk-free! Firefox can automatically import your bookmarks, passwords, history, and other data from Chrome without deleting it or interfering with any of its settings. Give it a try.


2 Answers

Tweaking your example you can see what's happening, and while the command is a bit contradictory, it looks like a bug. Define a as a function and log it instead of f, then have a look at the console. You'll see that a closure was created with a, f and g. Since a is referenced in g, and f and g should be visible to each other, it makes a bit of sense. But eval works in the global scope. So when you try to access them, you get undefined. It's like this closure cannot be accessed from anywhere.

Try:

eval('let a = function(){}; function f() {};function g(){a;};console.dir(a);'); 

You'll see this in the console:

<function scope>
    Closure
        a: function()
        f: function f()
        g: function g()

All your other cases make the situation clearer, and prevent the issue:

  • eval is not used: the scope mismatch is less obvious,
  • the code inside eval is surround with {}: the variables are linked through a Block scope.
  • a is not referenced in g: no need for a closure if the variables aren't linked.
  • let is changed to var: var in the global scope is defined in the global scope. So no Closure needed
  • "use strict" is added before the code: use strict in eval prevents variables to be added to the global scope, so again, "easier" to handle. No mismatch between having let needed to be linked with global functions.
like image 80
Julien Grégoire Avatar answered Oct 19 '22 12:10

Julien Grégoire


eval(`
    "use strict";
    let a = 0;
    console.log(f);
    function f(){
    }
    function g(){
        a;
    }
`);

Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

like image 24
strah Avatar answered Oct 19 '22 11:10

strah