📖 [강의 내용 및 개념 정리]
목차
이 글에서 저자는 자바스크립트의 "프로토타입 기반의 객체지향", "렉시컬스코프", "this", "스코프"와 같은 개념에 대해 한 논문을 참고하여 이야기를 풀어 설명해주십니다!
(*제 부족한 실력으로 논문을 요약하자면 다음과 같습니다.)
Rosch의 프로토타입 이론의 내용 중
"현실에 존재하는 것 중 가장 좋은 본보기가 원형(Prototyoe)이며, 문맥(Context)에 따라 범주, 즉 의미가 달라진다."
라는 내용이 있으며, 렉시컬 스코프(Lexical Scope)의 개념과 일맥상통한다.
MDN의 정의는
"함수와 함수가 선언된 어휘적(lexical) 환경의 조합을 말한다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다."
이다.
즉, 함수가 호출되는 환경과 별개로 기존에 선언되어 있던 환경, 즉 어휘적 환경을 기준으로 변수를 조회한다는 것이다.
MDN은 클로저(closure)를 다음과 같이 정의한다.
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). - mdn (2023)
즉, 클로저는 함수와 그 함수 주변의 상태의 주소 조합이다.
쉽게 풀어 쓰면, "클로저는 함수와 그 함수가 접근할 수 있는 변수의 조합"이라는 의미이다.
const globalVar = '전역 변수';
function outerFn() {
const outerFnVar = 'outer 함수 내의 변수';
const innerFn = function() {
return 'innerFn은 ' + outerFnVar + '와 ' + globalVar + '에 접근할 수 있습니다.';
}
return innerFn;
}
위 코드에서의 클로저 조합
클로저 함수: 외부 함수의 변수에 접근할 수 있는 내부 함수
클로저의 함수는 어디에서 호출되느냐와 무관하게 선언된 함수 주변 환경에 따라 접근할 수 있는 변수가 정해진다.
function createFoodRecipe (foodName) {
const getFoodRecipe = function (ingredient1, ingredient2) {
return `${ingredient1} + ${ingredient2} = ${foodName}!`;
}
return getFoodRecipe;
}
const highballRecipe = createFoodRecipe('하이볼');
highballRecipe('콜라', '위스키'); // '콜라 + 위스키 = 하이볼!'
highballRecipe('탄산수', '위스키'); // '탄산수 + 위스키 = 하이볼!'
highballRecipe('토닉워터', '연태고량주'); // '토닉워터 + 연태고량주 = 하이볼!'
highballRecipe 함수는 문자열 ‘하이볼’을 보존하고 있어서 전달인자를 추가로 전달할 필요가 없고, 다양한 하이볼 레시피를 하나의 함수로 제작할 수 있다.
여러 전달인자를 가진 함수를 연속적으로 리턴하는 함수
function makePancake(powder) {
return function (sugar) {
return function (pan) {
return `팬케이크 완성! 재료: ${powder}, ${sugar} 조리도구: ${pan}`;
}
}
}
const addSugar = makePancake('팬케이크가루');
const cookPancake = addSugar('백설탕');
const morningPancake = cookPancake('후라이팬');
// 팬케이크 완성! 재료: 팬케이크가루, 백설탕, 조리도구: 후라이팬
console.log(morningPancake);
const lunchPancake = cookPancake('냄비');
// 팬케이크 완성! 재료: 팬케이크가루, 백설탕, 조리도구: 냄비
console.log(lunchPancake);
중요!) 이와 같이 커링은 함수의 일부만 호출하거나, 일부 프로세스가 완료된 상태를 저장하기에 용이함
하지만, 커링으로 작성되지 않은 일반 함수는 모든 파라미터를 전달해야 하며, 일부를 생략하여 작성할 수 없다.
function makePancakeAtOnce (powder, sugar, pan) {
return `팬케이크 완성! 재료: ${powder}, ${sugar} 조리도구: ${pan}`;
}
const morningPancake = makePancakeAtOnce('팬케이크가루', '흑설탕', '후라이팬')
// 팬케이크 완성! 재료: 팬케이크가루, 흑설탕, 조리도구: 후라이팬
console.log(morningPancake);
모듈: 하나의 기능을 온전히 수행하기 위한 모든 코드를 가지고 있는 코드 모음으로, 하나의 단위로서 역할
중요!!!) 모듈은 다른 모듈에 의존적이지 않고 독립적이어야 함
function makeCalculator() {
let displayValue = 0;
return {
add: function(num) {
displayValue = displayValue + num;
},
subtract: function(num) {
displayValue = displayValue - num;
},
multiply: function(num) {
displayValue = displayValue * num;
},
divide: function(num) {
displayValue = displayValue / num;
},
reset: function() {
displayValue = 0;
},
display: function() {
return displayValue
}
}
}
const cal = makeCalculator();
cal.display(); // 0
cal.add(1);
cal.display(); // 1
console.log(displayValue) // ReferenceError: displayValue is not defined
displayValue는 makeCalculator의 코드 블록 외에 다른 곳에서는 접근이 불가능하지만,
cal의 메서드는 모두 클로저의 함수로서 displayValue에 접근할 수 있다.
이렇게 데이터를 다른 코드 실행으로부터 보호하는 개념을 정보 은닉(information hiding)이라고 하며, 이는 캡슐화(encapsulation)의 큰 특징이다.
중요!!!) 클로저는 특정 데이터를 다른 코드의 실행으로부터 보호해야 할 때 용이
medium - 자바스크립트 클로저로 Hooks구현하기
github 개인 블로그 - Vanilla Javascript로 React UseState Hook 만들기
velog - React Hooks - vanilla JavaScript로 구현하기
위 세개의 글에서 저자들은 자바스크립트 클로저 개념를 활용하여 React의 hook 기능을 바닐라 자바스크립트로 구현하는 과정을 설명해 주십니다!
위 아티클들을 참고하여 CustomReact 를 만들고 이 세팅 위에 개인 프로젝트를 진행하고 있다.
개인적으로 이러한 과정을 통해 자바스크립트의 기본 문법, 동작 원리들, 클로저와 같은 개념에 대해 궁금증을 가지고 공부하는 좋은 영향을 받아 추천하게 되었다.
간단하게라도 개인 프로젝트에 이 클로저 개념을 활용한 hook을 넣어보시면 어떠신지! 추천드리며 이번 포스팅은 마무리!!!