Search code examples
javascriptscopeecmascript-5iife

Block scope in ES5


I am having a problem with an assignment. This is the assignment:

Given following function.

let rechne = function(x,y,operation) {
  let ergebnis = x - y;
  if (!operation) {
    let ergebnis = x + y;
    console.log(ergebnis);
  }
  return ergebnis;
}

Rewrite the function so that the desired block scope of the variables can be achieved in ES5.

So I wrote this:

 let rechneScope = function(x,y,operation) {
   (function(){
     let ergebnis = x - y;
   })()

   if (!operation) {
     (function(){
       let ergebnis = x + y;
       console.log(ergebnis);
     })()
   }

   return ergebnis;
}

Presumed I called that function in a console.log like console.log(rechneScope(10, 2)) I would expect the first variable to be 8 and the second one to be 12.

But when I reload the browser, the console always prints 12 for the second variable and for the first variable the result differs. Sometimes 2, sometimes 8, sometimes 15. I am really confused. Why is this happening?


Solution

  • First, you're assumption that the desired output is 8 then 12 is wrong. The first console.log that gets executed is the one with ergebnis = x + y, so you should see 12 then 8.

    Next, let was introduced in ES6 so if you're limiting yourself to ES5, you're only allowed to use var.

    Finally, make sure your you wrap the entire scope of each variable in an IIFE. You have return ergebnis outside of the first function so that variable won't be in scope anymore at the time that line of code executes.

    The correct implementation would be something like this:

    var rechneScope = function(x, y, operation) {
      return (function() {
        var ergebnis = x - y;
        if (!operation) {
          (function() {
            var ergebnis = x + y;
            console.log(ergebnis);
          })()
        }
        return ergebnis;
      })()
    }
    
    console.log(rechneScope(10, 2))

    I know it's not part of your assignment, but just for reference, Babel doesn't bother with trying to emulate ES6 scope. Here's how the same thing would be compiled by Babel:

    "use strict";
    
    var rechne = function rechne(x, y, operation) {
      var ergebnis = x - y;
    
      if (!operation) {
        var _ergebnis = x + y;
    
        console.log(_ergebnis);
      }
    
      return ergebnis;
    };