8

I was testing if block scope can be used to replace IIFEs to create "private" variables through closures. It was going well until tested in Safari 11.0.3 (11604.5.6.1.1), which supports block scope, but has a bug with blocks and closures, e.g.:

{
  let i = 0;
  function getNext() {
    return i++;
  }
}
// Chrome and Firefox
console.log(getNext()); // 0
console.log(getNext()); // 1
// Safari
console.log(getNext()); // ReferenceError: Can't find variable: i

Is there a work around other than keep using IIFEs? Or is Safari correct and everyone else has a bug?

PS. In strict mode, getNext isn't defined outside the block either.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
RobG
  • 142,382
  • 31
  • 172
  • 209
  • 1
    Oh, this is definitely a Safari bug. How can you as a gold badge holder even be asking that? :P – Bergi Mar 13 '18 at 03:05
  • 2
    Interesting. Defining the functions as `var getNext = function() { return i++; }` Seems to work. I wonder if it is hoisting issue rather than scope issue. – Mark Mar 13 '18 at 03:10
  • @Mark_M OMG, how could I not notice that? The [weird half-hoisting of web-compat block-scoped function declaration](https://stackoverflow.com/a/31461615/1048572) probably is to blame, looks like that isn't implemented properly in Safari. @ Rob, just fix your code and write it so that it's valid in strict mode :-) – Bergi Mar 13 '18 at 03:41
  • @Bergi—really just wanted to post it 'cos it's weird. Saw someone saying "*IIFE's are bad, block scope is good*", but seems to me IIFEs aren't going anywhere. – RobG Mar 13 '18 at 03:56
  • @Mark_M—using *var* and a function expression seems to do the trick (in both modes), want to make it an answer? Might need to point out that function declarations are block scoped in strict mode but variables declarations aren't. – RobG Mar 13 '18 at 04:01
  • @RobG I'm still saying "*block scope is good*", but by that I implicitly mean strict mode block scope of course. Why would anyone want to use sloppy mode? – Bergi Mar 13 '18 at 04:09
  • @Bergi—I wasn't disparaging block scope or strict mode, just trying to see where IIFE behaviour was inconsistent with it before deciding to replace them with a new block-based pattern in future code. It seems strict mode + var + function expression does the job (i.e. provides consistent, equivalent behaviour across implementations), but more testing is required… – RobG Mar 13 '18 at 04:26

0 Answers0