[JS] - Scope 스코프 개념 완벽정리 1탄 (스코프 규칙 + 렉시컬 스코프)

sehannnnnnn·2022년 9월 11일
0

🥽 프로그래밍에서 스코프(Scope)란 ?

스코프 (scope)는 '범위'라는 뜻을 가지고 있다.
자바스크립트 뿐만 아니라 모든 프로그래밍 언어에서 스코프(scope) 란 말이 쓰이는데, 스코프는

스코프 : 변수또는 함수의 식별자가 사용되는 유효범위

라고 정의 할 수 있다.

let name = 'kim';
if (name) {
	let message = `Hello, ${name}!`;
  	console.log(message);
}

console.log(message);

위 예시와 같은 코드가 있다고 했을 때, 자바스크립트에선 변수가 선언된 위치에 따라 어디에서는 변수 사용이 불가할 때가 있다.

위 코드의 출력 결과는 아래와 같다.

Hello, Kim!
ReferenceError //message 변수를 찾을 수 없습니다.

자바스크립트의 스코프 규칙에 따라 let 키워드로 선언된 message라는 변수는 변수가 선언된 코드 블럭 {} 외부에서는 접근할 수 없기 때문에 Reference 에러를 출력하게 된다.

  • name : if 코드블럭 바깥에서 선언되었기 때문에 코드 전체에 해당하는 스코프를 가진다.
  • message : if 코드블럭 내부에서 선언되었기 때문에 if 문 안에서만 사용할 수 있다.

if 구문 뿐만 아닌 함수 function 블럭에서도 이러한 스코프에 구분은 생기게 되는데

let name = "lee";

function greeting () {
	let hi = 'hello!'
    console.log(hi + name);
}

console.log(hi);

위 코드의 출력 결과는 아래와 같다.

hello, lee!
ReferenceError //hi 변수를 찾을 수 없습니다.

이번에는 if구문이 아닌 함수 블럭에 의해 스코프에 구분이 생기게 되었고 함수스코프 내부에서 선언된 hi라는 변수는 함수 외부에서 접근할 수 없게 되었다.

스코프 규칙을 잘 알아두어야 선언된 변수를 불러올 수 없어 생기는 reference 에러를 방지할 수 있고, 고정되어야 하는 변수가 함수 내에서 바뀌게 되는 것을 방지할 수 있다.


📐 스코프의 규칙

위에 스코프 예시들을 보고 유추할 수 있는 규칙이 있다.

1. 내부에서 정의된 변수는 외부 스코프에서 접근이 불가능하다.
2. 외부에서 정의된 변수는 내부 스코프에서 접근이 가능하다.
3. 지역 스코프는 전역 스코프보다 더 높은 우선순위를 가진다.

  • 스코프는 부모와 자식 관계와 같이 중첩되어 있다.
  • 가장 바깥의 스코프는 전역 스코프(Global scope)라고 부르고 그 외 구분된 내부의 스코프들은 지역 스코프(Local scope)라고 부른다.

3번 규칙이 매우 중요한데 다음과 같은 예시가 있다.

let name = "김씨";

function showName () {
	let name = "이씨";
  	console.log(name);
}

console.log(name); //김씨
showName(); //이씨
console.log(name); //김씨

여기서 두개의 name 변수가 등장하는데 전역에있는 "김씨" 와 내부스코프에 있는 "이씨"가 있다.

  • 첫번째 console.log : 전역에 있는 name 김씨를 출력.
  • 두번째 console.log : showName() 함수가 실행되었기 때문에, 함수 내부에 console.log(name)을 실행 -> 지역 스코프의 name 이씨를 출력
  • 세번째 console.log : 첫번째와 마찬가지로 전역에 있는 name을 출력;

서로 다른 스코프에서 정의된 변수들은 그들의 변수명이 같더라도 엄연히 다른 변수 취급을 받는다.
스코프란 네임 스페이스(name space) 이다. _"자바스크립트 Deep Dive"

위 코드에서 함수스코프 내의 name 변수 앞 let을 제거해주면

let name = "김씨";

function showName () {
	name = "이씨";
  	console.log(name);
}

console.log(name); //김씨
showName(); //이씨
console.log(name); //이씨

이 경우 let 키워드가 없기 때문에 전역 변수로 존재하는 name 변수가 "이씨" 로 재할당 되었다. 하나의 name 변수만이 존재한다.

변수 뿐만 아니라 함수도!

변수 뿐만 아니라 함수 또한 스코프를 따른다.

function foo() {
    console.log('global function foo');
}

function bar() {
    function foo() {
        console.log('local function foo');
    }
    foo();
}

bar(); //local function foo
foo(); //global function foo

bar 함수 내에서 호출한 foo 함수는 해당 스코프 내에서 검색된 bar 내부의 foo 함수를 실행하며, 외부에서 호출한 foo 는 전역 스코프에 위치한 foo 함수를 실행한다.


렉시컬 스코프는 머죠?

렉시컬 스코프는 스코프 결정 방식 중 하나이다.

 var x = 1;
 function foo () {
  	var x = 10;
  	bar();
 }
 
 function bar() {
  	console.log(x);
  }![](https://velog.velcdn.com/images/rlatp1409/post/e42881ac-b9c9-44c1-b3b0-67ad979fb9e5/image.png)

	
foo();	 //1번
bar();	//2번

위와 같은 코드가 있을 때, bar에 수행 결과는 상위 스코프가 무었인지에 따라 결정되는데,

  • 함수를 어디서 호출했는지? (동적 스코프)
    => bar의 호출임으로 foo내부의 bar는 10을, 외부에 bar는 1을 출력.
  • 함수를 어디서 정의했는지? (렉시컬 스코프 또는 정적 스코프)
    => bar의 선언임으로 foo내부의 bar도 1을, 외부에 bar도 1을 출력.

여기서 두가지의 스코프 결정방식 중 첫번째를 동적 스코프 라고 하고, 두번째를 렉시컬 스코프라고 한다. 동적 스코프는 함수가 호출된 시점에 따라 상위 스코프를 결정해야하기 때문에 동적으로 바뀌게 된다.

자바스크립트는 이 두가지 방법중 렉시컬 스코프를 따르고 있다.

  • 따라서 함수를 어디에 호출했는지가 아닌 정의했는지에 따라 내부의 변수의 스코프가 결정된다.
  • 함수가 어디서 호출되었는지는 스코프 결정에 아무런 영향을 주지 못한다.

    따라서 위에 예제는 1을 두 번 출력하게 된다.

렉시컬 스코프는 클로저함수와 깊은 연관이 있다.

profile
FE 개발자 준비생 블로그 🪐

0개의 댓글