
✔️식별자(Identifier) vs 변수(Variable)
- 식별자 : 변수 포함해서 함수, 클래스, 객체 속성 등을 이름으로 구별하는 요소
= 변수, 함수, 클래스 등을 식별하는 이름 자체- 변수 : 데이터를 저장하는 메모리 공간
클로저 : 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우, A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상
function countWithoutClosure(){
let count = 0;
return count;
}
console.log(countWithoutClosure()); // 0
console.log(count);
// ReferenceError : count is not defined
- 함수가 실행되면, 함수 내부에 선언된 변수는 메모리 상에 올라간다
let count = 0;- return문 만나면 함수 종료, 가비지 컬렉터가
let count = 0회수한다- 변수에 접근 가능하려면, 변수가 메모리 상에 존재해야 하는데 함수 밖에서는 이미 변수가 제거되어서 참조할 수 없다
❗️함수 바깥에서도 실시간 확인하고 싶다면?
1.let count = 0을 전역으로 뺀다
→ 하지만 전역 변수는 어플리케이션에 계속 남아있기에 메모리 누수를 초래한다, 가독성도 낮다
2. 클로저 사용
함수 선언문 바깥에서도 스코프 접근 가능하다function countWithClosure(){ let count = 0; return{ increase : functIOn(){ count++; return count; }, decrease : function(){ count--; return count; }, getCount : function(){ return count; }, }; }const counter = createCounter(); console.log(counter.getCount()); // 0 counter.increase(); console.log(counter.getCount()); // 1 counter.decrese(); console.log(counter.getCount()); // 0counter 변수에 createCounter() 결과 저장
increase(), decrease(), getCount() 호출
❓함수 안에 또 함수를 return 하는 이유?
❓클로저 함수를 호출해서 꼭 변수에 할당하는 이유?
❓함수 바깥에서 스코프에 접근한다는 의미?
클로저 함수는 함수를 return
return count가 아니라return function increase ~~
근데return function increase ~~안을 보면count++; return count;즉, 상위 스코프 count 변수가 메모리 상에 없으면 실행할 수 없는 함수
클로저에 의해 return 될 때
함수 실행에 필요한 상위 스코프도 함께 메모리로 가져오는 것countWithClosure()
리액트가 이걸 대신 만들어주는 것(내부적으로)
❓왜 자바스크립트에서는 모든 함수가 클로저인가?
[[Environment]]프로퍼티와 렉시컬 환경
❗️몇몇 언어에서는 없기도 하는데 자바스크립트에서는 클로저가 된다
BUT 예외 존재
new Function 문법
https://ko.javascript.info/new-function
= 데이터를 해당 데이터에서 작동하는 함수와 연관시킬 수 있다
❗️자바스크립트는 결국 코드 대부분 이벤트 기반
→ 사용자가 이벤트를 발생시키면 코드는 콜백(이벤트에 대한 응답으로 실행되는 단일 함수)으로 연결된다
자바에는 메서드 private 선언이 가능 : 같은 클래스 내 다른 메서드에서만 호출 가능
하지만 예전 자바스크립트에는 private메서드 선언이 없기에 클로저를 사용한 것
✔️시뮬레이션(Simulation) vs 에뮬레이션(Emulation)
시뮬레이션(Simulation) : 완전 동일하게는 아닌, 비슷하게 일을 흉내낸다
에뮬레이션(Emulation) : 완전히 똑같은 방법으로 일을 흉내낸다
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log(outerVariable, innerVariable);
};
}
const closureFunc = outerFunction("Hello");
closureFunc("World"); // Hello, World
outerFunction이 실행된 후에도 innerFunction이 outerVariable을 기억하고 있어, 이후에도 접근이 가능하다
❓왜 전역 변수 사용을 지양해야 하나?
어느 디렉토리에서나 접근 가능하기 때문이다
브라우저 : window / Node.js : global
최상위 객체에 직접적인 조작을 가하면 유지보수 등에 문제 있다
function createCounter() {
let count = 0; // 상태를 유지하는 변수
return function () {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3
count는 createCounter()가 실행될 때 생성되었지만, 반환된 내부 함수에서 계속 참조할 수 있어 상태를 유지한다✔️콜백 함수, 프로미스(Promise)
✔️콜백 함수 : 비동기 처리를 위한 하나의 패턴
비동기 작업이 완료되었을 때 메인 스레드에서 실행할 함수
loadScript(script, callback)를 호출할 때, 함께 호출할callback함수가 준비되어 있어야 한다
loadScript를 호출하기 이전에 호출 결과로 무엇을 할지 미리 알고 있어야 한다
❗️콜백 헬(콜백 지옥) : 가독성이 안 좋은 코드, 여러 개의 비동기 처리를 한번에 처리하면서 생긴 문제
→ 해결방법 : 프로미스 등장
✔️프로미스(Promise) : ES6 비동기 처리를 위한 또 다른 패턴
언제 처리 할 지를 명시할 수 있어서 유용하다
프라미스를 이용하면 흐름이 자연스럽다
loadScript(script)로 스크립트를 읽고, 결과에 따라 그다음(.then)에 무엇을 할지에 대한 코드를 작성하면 된다let promise = new Promise(function(resolve, reject) { // executor (제작 코드, '가수') });
setTimeout, addEventListener 등에서 유용하게 사용된다null로 설정하여 제거한다✔️모듈(module)
여러 기능들에 관한 코드가 모여있는 하나의 파일
✔️일반 스크립트 vs 모듈
모듈은 항상 엄격모드(use strict) 모드로 실행된다
자기만의 스코프가 있다
동일 모듈이 여러 곳에서 사용되더라도 최초 호출 시 단 한 번만 실행된다
❓어디에서 클로저가 이루어질까?
function makeAdd(x) {
return function(y){
return x +y;
};
}
const add5 = makeAdd(5);
const add10 = makeAdd(10);
console.log(add5(2));