렉시컬 스코프 (Lexical Scope)
함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정되는 것
= 정적 스코프 (static scope)
↔ 동적 스코프 (dynamic scope) : 함수나 변수의 scope를 호출된 시점을 기준으로 한다.
자바스크립트를 포함한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따른다.
MDN 예제
function init() {
var name = "Mozilla"; // name은 init에 의해 생성된 지역 변수이다.
function displayName() {
// displayName() 은 내부 함수이며, 클로저다.
console.log(name); // 부모 함수에서 선언된 변수를 사용한다.
}
displayName();
}
init();
displayName() 내부에서 선언된 변수는 없지만, 외부 함수 init()의 변수 name에 접근할 수 있다.
즉, 중첩된 함수는 외부 범위에서 선언한 변수에도 접근할 수 있다.
var x = 1;
function print() {
console.log(x);
}
print(); //1
console.log(x); // 1
function dummy() {
var x = 999;
print();
console.log(`x: ${x}`);
}
console.log('----------------');
dummy(); // 1 //x: 999
console.log(x); // 1
- print() 함수가 선언되는 시점에 x = 1 이므로 print 함수 실행 결과 출력되는 값은 1이다.
- x 값만 출력해봐도 결과는 1이다.
- dummy()함수를 선언하변서 지역변수 x = 999로 선언한다.
그리고 내부에서 print함수를 통해 x값을 출력하면 1 이 출력된다.
print함수가 호출된 시점에는 x = 999 이지만, 선언된 시점에는 x= 1이기 때문이다.
= 중첩된 함수 print 는 외부의 전역 변수 x 에 접근할 수 있다.
- 다시 x를 콘솔에 찍어보면 전역변수인 x = 1 이 출력된다.
var x = 1;
function outer() {
var x = 2;
function inner() {
console.log(x)
}
inner();
}
outer();
- 전역변수 x = 1
- outer 함수 내의 지역변수 x = 2
그 안에서 inner 함수가 선언되고 x를 출력하는 동작을 한다.
따라서 inner함수가 선언되는 시점에서의 x = 2 가 출력될것이다.
함수 내부에서 선언된 inner함수가 변수 x를 찾는 순서
: 자신의 scope → 자신을 포함하는 외부함수 outer의 scope → 전역 scope
inner함수는 outer함수와 전역에 대한 scope chain 을 가지고 있다.
클로져 Closure 라는 개념과도 이어지는데..
자신이 생성된 시점의 환경을 기억하는 함수
=
외부 함수 호출이 종료되었음에도 Scope Chain을 이용해서 외부함수의 변수나 인자에 접근할 수 있는 함수
var x = 1;
function outer(z) {
var y = 2;
return function inner() {
console.log(x + y + z)
}
}
var sum = outer(3);
sum(3); //6
console.log(outer(3)); //[Function: inner]
- 전역변수 x를 선언
- z를 파라미터로 받는 outer 함수 를 선언
outer 함수 내부에서 y = 2로 선언
- 리턴받을 inner함수를 선언
- 함수 밖에서 outer(3) 을 호출하고 변수 sum에 할당한다.
- 변수 sum을 호출하면 x + y + z = 6 값을 출력한다.
이 결과는 inner 함수에서 이미 실행이 종료된 outer 함수의 변수 y와 인자 z에 접근했다는 말이 됩니다.
(이 말조차 이해가 안됨 ㅜㅜ)
여기서 중요한 점은 inner 함수가 클로저를 형성하여 자신이 선언될 때의 환경을 기억하고 있다는 것입니다. 즉, inner 함수는 outer 함수의 실행 컨텍스트에 있었던 y와 z에 접근할 수 있습니다.
var sum = outer(3);
이 시점에 outer함수를 호출하면서 인자로 3을 넘긴다.
→ z = 3, y= 2, inner함수가 반환된다. outer함수는 종료된다. 하지만 outer함수 내의 변수 y와 인자로 넘겨받은 z 값은 inner함수의 클로저로 인해 메모리에 유지된다.
그래서 그 뒤에 sum(3)에 의해 6이라는 값이 출력되는 것이다....
추가로 궁금해서 찍어본 outer함수는 inner함수를 리턴받기때문에 outer(3)을 콘솔에 찍어달라고하면 함수가 출력된다.
코드 및 내용 참조:
https://medium.com/sjk5766/lexical-scope-closure-%EC%A0%95%EB%A6%AC-41f5d1c928e4
'개발 공부 일지 > JavaScript' 카테고리의 다른 글
자바스크립트 - 렉시컬 스코프, 클로져, 비동기함수 (0) | 2024.08.07 |
---|---|
자바스크립트 - 무한 스크롤 (1) | 2024.08.04 |
복습 - 구조분해 (0) | 2024.07.30 |
자바스크립트 - 리퀘스트 보내기 (axios) (0) | 2024.07.27 |
자바스크립트 - 리퀘스트 보내기 (fetch, GET / POST) (0) | 2024.07.27 |