0

Just trying to wrap scoping around my head :-)

How can I refactor this code in order to be able to output 'a', 'b' and 'c' within function third()?

Any explanation without confusion and unnecessary theory would help.

var a = 1;

first = () => {
  let b = 2;
  second = () => {
    let c = 3;
    console.log(a, b); // Output 1, 2
    third(); // Output 1, 2, 3
  }
  console.log(a); // Output 1
  second();
}

third = () => {
  console.log(a, b, c);
}

first();
xianshenglu
  • 4,943
  • 3
  • 17
  • 34
  • 1
    pass the variables as an argument to `third` – gurvinder372 Apr 18 '18 at 06:37
  • As you defined `second()` inside `first()`, do the same for `third()` inside `second()`. which is [closure](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Durga Apr 18 '18 at 06:41

5 Answers5

1

b is not defined in the scope of the function third(). You will also get the same error for c. If you move the definition of third inside of second it will gain access to the scope of first and second since it would become a closure of them and then you will get expected behavior.

var a = 1;

first = () => {
  let b = 2;
  second = () => {
    let c = 3;
    console.log(a, b); // Output 1, 2
    third = () => {
        console.log(a, b, c);
    }
    third(); // Output 1, 2, 3
  }
  console.log(a); // Output 1
  second();
}


first();

EDIT: Typo

Garrigan Stafford
  • 1,331
  • 9
  • 20
0

The simplest answer is to simple make all three variables global by defining them outside of any function and just fill them with values when you need to.

var a = 1;
let b;
let c;

first = () => {
  b = 2;
  second = () => {
    c = 3;
    console.log(a, b); // Output 1, 2
    third(); // Output 1, 2, 3
  }
  console.log(a); // Output 1
  second();
}

third = () => {
  console.log(a, b, c);
}

first();
Sebastian Speitel
  • 7,166
  • 2
  • 19
  • 38
  • Hi Sebastian, and thanks for quick answers. That was my first (beginner approach) but I was hoping a different method just to fully understand lexical and execution scope. Maybe I'm just making things more complicated than they need to be :) Is there a way to not declare the variables in the global scope and still access them? – deeFall Apr 18 '18 at 06:50
  • @gurvinder372 explains two other solutions which aren't polluting the global scope – Sebastian Speitel Apr 18 '18 at 07:06
0

Hope, this is what you are looking for =>

var a = 1, b, c;

first = () => {
    b = 2;
    second = () => {
        c = 3;
        console.log(a, b); // Output 1, 2
        third(); // Output 1, 2, 3
     }
    console.log(a); // Output 1
    second();
}

third = () => {
    console.log(a, b, c);
}

first();
0

Any explanation without confusion and unnecessary theory would help

b and c are not locally scoped to first, so either define third where b and c are accessible

var a = 1;

first = () => {
  let b = 2;
  second = () => {
    let c = 3;
    console.log(a, b); 
    third = () => { //defined it inside second
      console.log(a, b, c);
    };
    third(); 
  }
  console.log(a); 
  second();
}

first();

Or, pass a, b and c as an argument to third while invoking the same.

var a = 1;

first = () => {
  let b = 2;
  second = () => {
    let c = 3;
    console.log(a, b);
    third(a,b,c); // pass a, b and c as parameters
  }
  console.log(a); 
  second();
}

third = (a,b,c) => { //accept a, b and c
  console.log(a, b, c);
}

first();
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
0

In comments it's written right that you have to pass your variables. Function third has an access to the variable a but not to b and c, since they are scoped locally in function first and second.

Functions look for a variable within themselves, then within parent and so on towards the global.

So function second contains variable c, but not a and b. It looks within it's parent which has variable b and then global variable a. However, function third is not nested, so the next scope it looks for a variable is global scope which contains only variable a

Sergey
  • 7,184
  • 13
  • 42
  • 85