I'm reading Kyle Simpson: ES6 & Beyond and I am at the second chapter. In the section titled "Block-Scoped Functions" an example is given:
{
foo(); // works!
function foo() {
console.log("works!");
}
}
foo(); // ReferenceError
(the console.log
was added by me for testability.)
I would expect this code to run foo
successfully at the first call, even though the function is defined below the call and to crash at the second call due to ReferenceError, as the book is claiming. However, if I run this in Chromium (Version 71.0.3578.98 (Official Build) snap (64-bit)) both function
calls are successfully executed and "works!"
is outputted twice to the console. If I run the same script in FireFox, then the first function call does not log anything and the second function call, outside the scope is outputting "works!"
. So, Chromium and FireFox behave differently from each-other and from the expectations drawn from the book. I have transpiled this in babeljs.io and the result was:
"use strict";
{
// works!
var _foo = function _foo() {
console.log("works!");
};
_foo();
}
foo(); // ReferenceError
Strangely, foo is
defined as function
scope, (the keyword var
is used instead of the keyword let
or const
), so it is reachable from outside the scope, yet the call outside the scope was not changed to _foo
, hence we will have an error, but if we change the script to
{
foo(); // works!
function foo() {
console.log("works!");
}
}
window["foo"](); // ReferenceError
the transpiler does not change the name of foo
to _foo
. With all these experiments I have reached to the conclusion that if I intend to have a block-scoped function, I need to define it explicitly, like:
{
foo(); // works!
let foo = function() {
console.log("works!");
};
}
foo(); // ReferenceError
but then even the first call for foo
crashes due to temporal dead zone issue. So, my question is: Why does a block-scoped function
work outside the scope?