The problem is that the code is in loose mode and you're declaring a function in a block. Function declarations in blocks were only standardized in ES2015 and, well, they make sense in strict mode but in loose mode they're...weird.
In strict mode, your code works, possibly as you expect or possibly not. bob
is accessible to b
...and neither bob
nor b
accessible outside that block, unless you do something to expose them outside it.
Here's an example you can use to test it on both Safari and iOS Safari (I have only the latter available to me). This version gives an error:
<script>
window.onerror = e => {
document.body.insertAdjacentText("beforeend", String(e));
};
</script>
<script>
{
let bob = 5;
function b() {
document.body.insertAdjacentText("beforeend", bob++);
}
b();
}
</script>
The error is:
ReferenceError: Can't find variable: bob
This version works:
<script>
window.onerror = e => {
document.body.insertAdjacentText("beforeend", String(e));
};
</script>
<script>
"use strict"; // <============================
{
let bob = 5;
function b() {
document.body.insertAdjacentText("beforeend", bob++);
}
b();
}
</script>
I have also replicated the behavior in the latest version of JavaScriptCore (Apple's JavaScript engine), v265499. I installed¹ and ran it locally (changing console.log
/insertAdjacentText
to print
, which is available in most of the raw engine executables) and get the same error in loose mode and not in strict mode.
If you want b
available outside the block, you're probably better off doing something like this:
"use strict";
const b = (() => {
let bob = 5;
return function b() {
console.log(bob++);
};
})();
b();
Which is a lot bulkier, but... Alternatively, with let
:
"use strict";
let b;
{
let bob = 5;
b = function b() {
print(bob++);
};
}
b();
¹ Using the very handy jsvu
utility.