본문 바로가기

기술들/javascript

[공부했던 것 정리] Scope(2)

저번에 이어서 function Scope와 block Scope를 비교해 보겠다. 

 

function Scope는 앞에서 정리했던 local Scope와 같이 함수 영역을 의미하고, 

block Scope는 중괄호로 시작하고 끝나는 범위를 말한다.

예를 들어 for { block 범위 } 문,  if { block 범위  }문이 이에 해당한다. 

let ?

이 블록범위에서만 변수를 사용할 수 있게 만드는 변수타입이 바로 let이다.

block 범위 안에서 let 으로 변수를 지정해주면, 그 변수는 그 block 범위 밖에서 사용할 수  없다.

반대로 block 범위가 아닌 전역범위에서 let으로 변수를 선언해줄 경우 그 변수는 어디서든 사용할 수 있다.

 

위 그림에서 (1) 과 (2) 는 어떤 결과값을 나타낼까? 

 

(1) 'true' 

(2)  Reference Error

    

 

 

(1)은 if 문의 block범위 안에 전역범위에서 선언해준 saying이란 변수를 사용하였다. 전역범위에서 선언해준 변수는 어디서든 사용할 수 있기 때문에 saying에 할당된 'true'가 콘솔 창에 표시 되었다. 

(2)는 isTrue란 변수를 전역범위에서 사용했는데, 이 변수를 정의한 곳을 찾아보니 block범위 안에서 정의를 해주었다. 

let은 block Scope를 따르기 때문에 let으로 변수가 block Scope에서 정의되면 그 변수는 block 밖에서는 사용할 수 없다. 그렇기 때문에 전역범위에서 isTrue는 정의되지 않았다고 표시되는 것이다. 

 

위에서 변수타입 let은 block Scope를 따른다고 했다. 즉, 이 말은 block에서 let으로 변수가 정의되면  그 변수는 그 block범위에서만 사용가능하다는 의미이다. 

var ?

그렇다면 다른 변수타입인 var은?? 

변수타입 var은 function Scope를 따른다. function(함수)내에서 var로 변수를 정의하면 그 변수는 함수내에서만 사용할 수 있다. 그러나 if문이나 for문과 같은 block범위에서 var로 변수를 정의하거나 전역범위에서 정의하면 그 변수는 어디서든 사용할 수 있다. 이를 바탕으로 아래 (1)~(5)를 유추해보면..

앞에 설명했던 것을 참고하여 답을 살펴보면

(1) 't1' (함수가 아닌 다른 block 또는 전역에서 var로 선언된 변수는 어디서든 사용가능)

(2) 't2' (함수가 아닌 다른 block 또는 전역에서 var로 선언된 변수는 어디서든 사용가능)

(3) 't2' (함수가 아닌 다른 block 또는 전역에서 var로 선언된 변수는 어디서든 사용가능)

(4) Reference Error(함수내에 var로 정의된 변수는 함수 밖에서 사용못함)

(5) 't3'

 

다음과 같은 경우도 있다. 만약 전역범위에서 let이나 var로 변수를 정의해주고

var test1 = "t1";

 

새로운 block(함수, if문, for문)에서 재정의를 한다면 그 재정의 된 변수값은 전역변수가 되어 어디서든 사용할 수 있다. 

if(true) {
  test1 = "t2";   // block내에서 재정의
  console.log(test1); // "t2"

test1; // "t2" /block밖에서 변수호출, 처음 정의해준 test1과 값이 달라짐

즉, 전역범위에 선언된 변수를 어디서든 재정의를 해주면 그 값이 어디에서 재정의가 되었든 모든 곳에서 쓸 수 있는 전역변수가 된다. 

(여기서 재정의란,  let이나 var로 정의된 변수를 let, var을 쓰지않고 다시 새로운 값으로 할당해주는 것을 의미한다.)

단, 재선언은 let은 할 수 없고 var만 가능하다. (재선언은 let, var을 쓰고 사용했던 변수를 다시 정의해주는 것을 의미한다) 

 

지금까지의 설명을 표로 정리해보았다.  

  var let const
유효범위 function block block
재정의 가능 가능 불가능
재선언 가능   불가능 불가능

const는 html의 id와 비슷하게 변하지 않는 고유한 곳에 쓰인다. 즉, 특정값을 나타내는 상수에 많이 쓰인다. 

ex) const PI = 3.14;  // 만약 변하지 않는 PI값을 실수로 재선언이나 재정의를 하면 에러가 발생할 수 있기 때문에, 그렇게 할 수 없게 하기 위해 const를 쓰는것이다. 

 

let 과 var의 차이 ?

let과 const는 2015년에 도입되었다. 그 전까지는 var만 사용하였다. var은 let에 비해 자유롭다. 재정의, 재선언이 모두 가능하고 let에 비해 사용할 수 있는 유효범위도 넓기 때문이다. 그렇지만 이러한 자유로움이 좋은 것은 아니다. 분명 복잡한 코드를 짜다보면 여러 변수를 사용할테고 자신이 어떠한 변수를 선언했는지 헷갈릴 수 있다. 즉, 이미 정의했던 어떤 중요한 변수를 또 다른 값으로 재정의해 버릴 수가 있는 것이다(=변수중복). var은 재정의가 가능하고 if나 for문의 block은 쉽게 넘어갈 수 있기 때문에 체계적인 변수 관리를 할 수 없다. 

그렇지만 let은 유효범위가 모든 block이어서 제한이 삼엄하고 또한 재선언을 할 수 없기 때문에 자신이 어떠한 변수를 선언했었는지 (에러를 통해?) 알 수 있다. 즉, 체계적인 변수 관리가 가능하다. 

 

이와 관련해서 하지 말아야 할 행동이 있다. 바로 변수 타입없이 변수를 정의하는 것이다. 이는 전역변수를 선언하는 것인데, let이나 var 없이 block범위 내에  변수를 선언하면 전역변수가 되기 때문에 어디서든 사용할 수 있어, 변수 중복이 발생할 수 있는 것이다. 항상 변수를 쓸 때는 신중에 신중을 가해야 한다.