[JS 33가지] 6. 스코프(Scope)

2020. 7. 5. 23:27Javascript/33가지 개념

스코프(Scope)

 자바스크립트에서 스코프는 어떤 변수에 접근할 수 있는지 없는지를 정의한다. 스코프는 크게 전역 스코프, 지역 스코프로 나뉜다.

 

전역 스코프(Global Scope)

 전역 스코프는 모든 함수에 속하지 않고, 블록({})안에도 속하지 않은 가장 바깥에 있는 범위를 말한다. 그리고 전역 스코프에 있는 변수를 우리는 전역 변수라고 한다. 전역 변수를 선언하면 어느 블록이든지 간에 선언된 전역변수를 사용할 수 있다.

const greeting = "Hello!";

function sayHello(){
  console.log(greeting);
}

sayHello();       // "Hello!"

 

지역 스코프(Local Scope)

 지역 스코프는 함수, 블록({})과 같이 특정 범위를 가리킨다. 지역 스코프안에 있는 변수를 우리는 지역 변수라고 부른다. 자바스크립트에서는 함수, 블록 두 종류의 스코프 존재한다.

 

 

 함수 스코프는 함수 범위를 말한다. 함수 스코프 안에서 변수를 선언했을 경우, 함수 안에서만 이 변수에 접근할 수 있다. 

function sayHello(){
  const greeting = "Hello!";
}

console.log(greeting); // Error: greeting is not defined.

 

 또한 함수 스코프는 각자의 스코프에 접근할 수 없다.

function sayHello(){
  const hello = "hello";
  console.log(hi);
}

function sayHi(){
  const hi = "hi";
  console.log(hello);
}

sayHello();   // hi is not defined.
sayHi();      // hello is not defined.

 

 하지만, 함수가 다른 함수에서 만들어진 상황에서, 안쪽함수는 바깥함수의 변수에 접근할 수 있다. 이것을 어휘적 스코프(lexical Scope)라고 한다.

function outerFunction () {
	const outer = `I see the outer variable!`;
    
   return function() {
    	console.log(outer);
    }();
}

outerFunction();

 

 

 블록 스코프는 블록({})안에 있는 범위를 말한다. 블록 스코프 안에서 변수를 선언했을 경우, 블록 안에서만 이 변수에 접근할 수 있다.

{
  const greeting = "Hello!";
}

console.log(greeting); // Error: greeting is not defined.

 

 

함수 호이스팅(Hoisting)

Hoisting은 끌어올리다라는 사전적 의미를 갖고 있다. 자바스크립트에서 함수는 다음과 같이 표현할 수 있다.

sayHello();

function sayHello(){             // (1)
  console.log("Hello");
}

const sayHello = function(){     // (2)
  console.log("Hello");
}

 

 (1)과 같이 표현한 함수를 우리는 함수 표현식이라고 부르고, (2)와 같이 선언한 함수를 우리는 함수 선언식이라고 부른다. 위 프로그래밍을 실행하면 결과는 당연히 에러다. 자바스크립트 개발자들은 함수 표현식 보다 함수 선언식을 쓸 것을 권장하고 있다. 그 이유는 다음과 같다.

function sayHello(){             // (1)
  console.log("Hello");
}

sayHello();
sayHello();

function sayHello(){             // (2)
  console.log("Hello");
}

 

 위 두 프로그램의 결과가 똑같이 Hello를 출력하기 때문이다. 그 이유는 함수 표현식을 이용하면 함수가 호이스팅되기 때문이다. 좀 더 쉽게 말하자면 함수 표현식을 이용하면 코드가 순서대로 실행되지 않고, 호이스팅되어 가장 먼저 실행된다. (2)의 경우를 보면 첫 번째 줄에 있는 sayHello()보다 function sayHello(){ ... } 구문이 먼저 실행된다. 하지만 함수 선언식을 이용하면 에러가 난다.

sayHello();

const sayHello = function(){         
  console.log("Hello");
}

 

 이런 이유로 개발자들은 함수 선언식을 이용할 것을 권하고 있다. 왜냐하면 항상 함수는 선언 전에 미리 사용해야하기 때문이다.

 

예약어 Var

변수를 선언할 때 사용하는 예약어 var도 호이스팅된다. 다음 프로그래밍을 보면 알 수 있다.

if(true){
  var greeting = "hello";
}

console.log(greeting);

 

 위 코드를 실행하면 에러가 발생하지 않는다. 그 이유는 var greeting 코드가 호이스팅되기 때문이다. 이런 이유로 다음 코드 역시 에러가 나지 않는다.

for(var num = 1; num<=3; num++)
  console.log(num);

console.log(num);   // 4

 

 또한, var 예약어를 이용해서 똑같은 변수명을 선언해도 오류가 나지 않고 실행된다. 왜냐하면 두 번째 변수가 첫 번째 변수를 덮어쓰기 때문이다. 이는 함수 선언식도 마찬가지다.

var num = 123;
var num = 124;

console.log(num);  // 124
sayHello();        // hi

function sayHello(){
  console.log("hello");
}

function sayHello(){
  console.log("hi");
}

 

 따라서 변수를 선언할 때const, let 예약어를 사용하도록 하자.

 

 

참고 자료