Home [Javascript] 함수 scope
Post
Cancel

[Javascript] 함수 scope

Javascript에서는 스코프(scope)라는 개념이 존재한다.

스코프는 범위라는 뜻으로 자바스크립트에서 어떤 의미를 가지는지 알아보자.

자바스크립트에서는 보통 변수에 값을 담아 사용하는데, 이때 변수는 지역변수전역변수로 나뉘어진다.

전역변수와 지역변수

자바스크립트에서 함수 안에 포함되지 않은 가장 바깥의 범위에 변수를 전역(global)변수라 하고 함수 내에서 정의한 변수를 지역(local)변수라 한다.

1
2
3
4
5
6
7
8
9
let a = 'global';

function scopeEx() {
	let a = 'local';
	a = 'change';
}

scopeEx(); 
alert(a); // 'global'

위 코드를 보면 함수 바깥에서 전역으로 선언한 전역변수 a가 있고, 함수 내에서 지역으로 선언한 지역변수 a가 있다.

함수를 호출하면 a라는 함수에 change라는 값이 들어가야 하는데 결과를 보면 아직 global인 것을 알 수 있다.

그 이유는 자바스크립트에 함수 스코프라는 개념 때문이다.

스코프(scope)

스코프는 범위라는 뜻을 가지고있듯이 함수 내에서 선언된 변수는 그 함수 내에서만 사용 할 수 있다는 것이다.

위 코드에서 let a = 'local' 이라고 선언된 지역변수 a는 scopeEx() 함수 내에서만 사용할 수 있다.

1
2
3
4
5
6
7
8
9
let a = 'global';

function scopeEx() {
	let a = 'local'; 
	a = 'change'; // 지역변수 a에 값을 바꿈
}

scopeEx(); 
alert(a); // 전역변수 a의 값
1
2
3
4
5
6
7
let a = 'global';

function scopeEx() {
	a = 'change';
}
scopeEx();
alert(a); // 'change'

따라서 함수 scope로 인해 함수 내에서 값을 변경한 a는 지역변수 a이고, 함수 밖에서 alert으로 출력한 a는 전역변수 a의 값이 되는 것이다.

자바스크립트는 변수의 범위를 호출한 함수의 지역 스코프 부터 전역 변수들이 있는 전역 스코프까지 점차 넓혀가며 찾는데, 첫번째 예시에서는 지역 스코프인 scopeEx() 함수 내에서 지역변수 a를 찾았기 때문에 지역변수 a의 값을 바꾼 것이다.

스코프 체인(scope chain)

전역변수와 지역변수의 관계에서 스코프 체인(scope chain)이라는 개념이 나오게 된다. 위에서 배운 내용을 요약하자면 내부 함수에서는 외부 함수의 변수에 접근 가능하지만 외부 함수에서는 내부 함수의 변수에 접근 할 수 없다는 것이다.

1
2
3
4
5
6
7
8
9
10
11
let global = 'global';
function scopeEx() {
	console.log('scopeEx 내부에서 global 출력', global); // global
	function scopeChainEx() {
		let local = 'local';
		console.log('scopeChainEx 내부 에서 global 출력', global); // global
	}
	scopeChainEx();
}
scopeEx();
console.log(local); // undefined

위 예시를 보면 scopeChainEx() 함수는 global 변수를 찾기 위해 먼저 자기 자신의 스코프인 scopeChainEx() 내에서 찾고, 없으면 한 단계 올라가 scopeEx() 내에서 찾고, 또 없으면 다시 올라가 전역 스코프에서 찾게 된다.

결국 전역 스코프에서 global 변수를 찾아 ‘global’ 값을 콘솔에 출력한다. 만약 전역 스코프에서도 변수를 찾지 못하면 변수를 찾지 못했다는 에러가 발생한다. 이렇게 변수를 찾기 위해 꼬리를 물고 범위를 넓혀나가는 관계스코프 체인이라 한다.

렉시컬 스코핑(lexical scoping)

스코프는 함수를 호출할 때가 아닌 선언할 때 생긴다. 이 개념이 바로 렉시컬 스코핑이다.

💡 스코프는 함수 선언 시 결정된다.

렉시컬 스코핑은 다른 말로 정적 스코프(static scope)라고 부르기도 한다.

1
2
3
4
5
6
7
8
9
10
11
let scope = 'scope';

function log() {
  console.log(scope); // scope
}

function lexicalScopeEx() {
  let scope = 'lexical scope';
  log();
}
lexicalScopeEx();

이제껏 배웠던 스코프의 개념인 지역변수에서 전역변수로 영역을 확장해나가며 변수를 찾는 스코프의 특징을 생각해보면 변수 scope의 값은 lexicalScopeEx() 함수내에서 먼저 찾을 수 있기 때문에 콘솔에는 lexical scope가 찍힐 것이라고 예상할 수 있다. 하지만 콘솔에는 scope가 찍히게 된다.

이게 바로 앞서 말했듯이 스코프는 호출할 때가 아닌 선언할 때 결정되기 때문이다.

함수를 선언하는 순간부터 함수 내부의 변수는 자기 스코프로 부터 가장 가까운 곳에 있는 변수를 계속 참조하게 되는데, 위 예시에서는 log 함수 안의 scope 변수는 선언 시 가장 가까운 전역변수 scope를 참조하게 되어 콘솔에 scope가 찍히게 되는 것 이다.

참조 : https://www.zerocho.com/category/Javascript/post/5740531574288ebc5f2ba97e

This post is licensed under CC BY 4.0 by the author.