[DAY22] JavaScript 복습

m1njae·2022년 1월 24일
0

22 Basic Challenge

목록 보기
22/25
post-thumbnail

JavaScipt에 대해서 복습과정에서 스코프와 클로저에 대한 개념도 추가적으로 정리하면서 챌린지를 마무리지으려고 한다.

스코프(Scope)

JavaScript에서 스코프(Scope)란 작성된 코드를 둘러싼 환경으로, 어떤 변수들에 접근할 수 있는지를 정의한다. 스코프는 전역(global)지역(local)으로 정의할 수 있다. 흔히 이해하고 있는 전역 변수와 지역 변수와 비슷한 개념이다. 그러나 JavaScript는 다른 언어들과는 달리 Function-level scope(함수 레벨 스코프)를 사용한다.

Block-level vs Function-level

대부분의 언어는 Block-level scope를 사용함으로써 변수 선언이 코드 블록 단위로 유효하다. 그러나 Function-level scope는 함수 내 선언된 변수는 함수 블록 내에서만 유효하나 함수 외부에서는 변수를 활용할 수 없다.

function foo() {
   if (true) {
       var a = 0; 
       console.log(a);
   }
   console.log(a); 
}

위 코드를 참조해보면, 다른 프로그래밍 언어의 경우, Block-level scope를 사용하기에 조건문과 반복문 안에서 선언된 변수를 중괄호 밖에서 출력할 수 없지만, JavaScript는 Function-level scope를 사용하므로 중괄호 밖에서 변수 출력이 가능하다.

JavaScript ES6부터는 constlet을 통해 Block-level scope도 지원하기 시작했다. 따라서 if 문 안에 var 대신 const나 let으로 변수를 선언하면, 다른 언어들처럼 참조하지 못한다. const와 let은 block-level scope, var는 Function-level scope이라는 것을 기억하자.

전역(global) 스코프 / 지역(local) 스코프

  • 전역(global) 스코프
    변수가 함수 외부나 중괄호{} 외부에서 선언되었다면, 전역 스코프에 정의되었다고 한다. 전역 스코프에 변수를 선언하면 코드 어디에서나 해당 변수를 사용할 수 있다.

  • 지역(local) 스코프
    지역 스코프는 함수 내의 범위로, 각각의 함수마다 자신의 지역 스코프를 가지고 있다. 어떤 함수 내의 지역 스코프에 선언된 변수가 있다면, 그 함수 외부에서는 그 변수를 참조할 수 없다. 따라서 각각 선언된 함수가 있다면 서로의 스코프에 있는 변수도 참조할 수 없다.

var global_scope = 'global';  // 전역 스코프

var local_function = function() {
    var local_scope = 'minjae';  // 지역 스코프
    console.log(global_scope);  // 전역 스코프 참조 가능. global 출력
    console.log(local_scope);  // 함수 내이기 때문에 지역 스코프 참조 가능. minjae 출력
};

console.log(local_scope);  // local_scope는 지역스코프이기 때문에 에러 발생.

스코프 체인(Scope chain)

var a = 1;

function outer() {
	var b = 2;
	console.log(a); // 1
	
	function inner() {
		var c = 3;
		console.log(b);
		console.log(a); 
	}
	
	inner();  // 2 1
}
outer();

console.log(c);  // c is not defined

inner 함수에서는 a변수를 참조할 때 먼저 자신의 스코프에서 a를 찾고, 없으면 상위 스코프인 outer 함수의 스코프에서 a를 찾고, 거기에도 없으면 상위 스코프인 전역 범위로 올라가 a를 찾는다.
최종적으로 전역 스코프에도 찾는 변수가 없으면 not defined 에러를 출력한다. 이렇게 계속해서 체인처럼 상위 스코프를 참조하기 때문에 스코프 체인(Scope chain)이라고 한다.

렉시컬 스코프(Lexical scope)

렉시컬 스코프(Lexical scope)란, 함수를 어디서 호출하는지가 아니라 어떤 스코프에 선언하였는지에 따라 결정된다.

var text = 'global';

function foo() {
	console.log(text);
}

function bar() {
	var text = 'bar';
	foo();
}

bar(); 

//실행결과
global

bar()를 출력했을 때, text 변수를 'bar'로 선언했어도 'global'이 출력된다. 어디서 호출하는지가 아니라 처음 선언되었을 때에 어떤 스코프에 있는지가 중요하기 때문이다. 즉, 스코프란 코드를 실행하면서 변경되는 것이 아니라 처음 선언된 스코프로 결정된다. 따라서 무조건 자기 자신의 스코프를 찾아보고 그 이후에는 전역 스코프를 찾게 되는 것이다.

클로저(closure)

일반적으로 외부 함수의 실행이 끝나면 외부 함수가 소멸되어 내부 함수가 외부 함수의 변수에 접근할 수 없다. 하지만 "외부 함수의 실행이 끝나고 외부 함수가 소멸된 이후에도 내부 함수가 외부 함수의 변수에 접근할 수 있는 구조"를 클로저(closure)라고 한다. 다시 말하면, 외부함수가 리턴되어 사라져야 하는데 사라지지 않고 내부 함수의 참조로 인해 값을 유지하게 되는 것이다. 이때 내부 함수를 클로저 함수라고 한다.

function f(arg) {
	var n = function() {
		return arg; 
	}
	arg++;
	return n; 
}

var m = f(123); 
console.log(m());

//실행결과
124

n을 언뜻 보기에는 f(123)을 실행하게 되면 함수 n에서 이미 arg를 반환하였기 때문에 n이 가지는 범위에서 arg 값은 123이라고 생각할 수 있지만 함수 n은 함수 f의 범위에 있는 것을 참조하고 있기 때문에 함수 f에서 모든 처리가 끝나고 나서야 함수 n이 처리된다. 따라서 f(123)는 124이다.

보통 함수 내에서 사용된 지역 변수는 해당 함수의 실행이 종료되면 파기되는 것인데, 클로저 함수에 의해 계속 참조되고 있는 경우에는 해당 지역 변수를 파기하지 않고 계속 보관하고 있게 된다.

챌린지를 마치며

이로서 22일간의 챌린지를 마무리 지을 수 있었다. 22일동안 많은 경험을 얻었다. 무엇보다 중요한 경험은 적은 양이더라도 매일같이 꾸준히 하는 습관을 들이면서 공부 내용을 기록하는 습관도 가지게 된 것이다.

챌린지를 진행하면서 Node.js와 MySQL을 배웠지만 함께 응용하는 미션이 없었던 것이 약간의 아쉬움이었다. 그러나 챌린지가 끝난다고 공부를 멈추는 것은 아니니 그것은 이제 나의 몫이라고 생각한다. 또한 SQL에 대한 공부를 위해 sqld 자격증을 취득해볼 생각이 있다.

22일간 공부하고 배운 모든 것들을 완벽하게 이해했다고 하면 거짓말인 것 같다. 당장 오늘 정리한 클로저에 대해서도 누군가 설명하라고 그러면 어버버 거릴 것 같다. 익숙한 것과 이해하고 있는 것의 차이를 더 명확히 알게 되었다. 그래도 익숙해지면 나중에 이해하기 수월해지지 않을까 이를 통해서 내가 아는 것과 모르는 것을 인지하고 있는 것도 중요하다는 것을 느꼈다.

챌린지를 진행하면서 개발에 대한 관심과 약간의 실력도 얻었지만 내가 어떠한 마음가짐으로 나아가야하는지에 대한 태도와 자세를 확립할 수 있었다는 점에서 긍정적으로 다가왔다. 지금 잡혀있는 습관들과 태도, 자세를 계속해서 유지하는 것이 나의 다음 목표이다. 🔥올해는 다르다!🔥

참고

한 눈에 끝내는 node.js

profile
할 수 있는 것부터 차근차근, 항해자의 공부 기록공간

0개의 댓글