[JavaScript] Closure

Main·2023년 6월 5일
0

JavaScript

목록 보기
2/10
post-thumbnail

Closure?

어떤 함수에서 선언한 변수를 참조하는 내부함수를 외부로 전달하는 경우 외부 함수가 종료된 이후에도 외부함수에서 선언한 변수가 사라지지 않는 현상
즉, 내부 함수에서 외부함수의 값에 접근할 수 있다는 개념

closure 예시 코드

let outer = function () {
	let a = 1;
    const inner = function() {
	   console.log(++a);
    }
    return inner;
}
let outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3
outer2 = null;

inner() 함수에서는 a를 선언하지 않았지만 접근이 가능
=> 환경 레코드(enviromentRecord)에서 a값을 찾기 못하므로 외부 환경 레코드(outerEnviromentRecord)를 통해 지정된 외부환경참조(outerEnviromentReference)의 상위 컨텍스트 렉시컬환경(LexicalEnviroment, 내부 함수가 선언됐을 때의 스코프)에 접근해서 a값을 찾기 때문에 접근이 가능

inner 함수의 실행 시점에서 outer 함수는 이미 실행 종료 되었지만 outer 함수의 렉시컬 환경에 접근을 통해 a값에 접근이 가능

=> 가비지 컬렉터의 동작방식이 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집 대상에 포함하지 않기 때문에 렉시컬 환경이 사라지지않고 접근이 가능
위의 특성 때문에 closure 는 메모누수 주의가 필요
=> 이를 해결하기 위해 필요가 없어진 시점에서 null이나 undefined를 할당하여 해결

Closure 활용

1. 콜백함수 내부에서 외부 데이터를 사용할 때

const cutting  = (cb) => {
	cb();
}
const cook = (food) => {
	cutting(()=>console.log(`${food} 손질중 입니다.`));
}

cook 함수의 인자로 받아온 food값을 cutting 함수에서도 사용
cook 함수가 종료되어도 cutting 함수는 food값에 접근이 가능
=> cutting 함수가 실행될 때 outerEnvironmentReference가 LexicalEnvironment를 참조하여 food 값에 접근이 가능한 것


2. 정보은닉

const createCharacter = (name) => {
    let _name = name;
  	let hp = 10;
  	let power = 5;
  	
  	return {
     get myInfo() {
     	  return { name: _name, hp: hp, power: power }
     	},
	 set name(newName){
		_name = newName;
       console.log("change name");
		}
    }
}
const myCharacter  = createCharacter("Jon");
Jon.myInfo // {name: 'Jon', hp: 10, power: 5}
Jon.name = "Jon2" // change name
Jon.hp = 100// undefined
Jon.power = 100//undefined

외부에서는 name, hp, power 정보를 읽을 수 있고, name 값만을 변경할 수 있음
외부에서는 hp, power값을 변경할 수 없음


3. 커링 함수(여러개 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출하도록 체인 형태로 구성한 것)

const curry = function(func) {
  return function(a) {
    return function(b) {
      return function(c) {
        return function(d) {
          return function(e) {
          	return func(a, b, c, d, e);
          }
        }
      }
    }
  }
}
const getMax = curry(Math.max);
console.log(getMax(10)(90)(35)(200)(100))

커링은 한 번에 하나의 인자만 전달하는게 원칙
중간 과정상의 함수를 실행한 결과는 다음 인자를 받기 위해 대기할 뿐, 마지막 인자가 전달되기 전까지는 원본 함수가 실행되지 않음
=> 지연 실행을 사용할 상황에 적합

커링 ES6 화살표 함수를 이용하여 축약형으로 표기

const curry = func => a => b => c => d => e =>func(a,b,c,d,e);
const getMax = curry(Math.max);
console.log(getMax(10)(90)(35)(200)(100));

마무리 정리

  • Closure는 어떤 함수에서 선언한 변수를 참조하는 내부함수를 외부로 전달할 경우, 함수의 실행 컨텍스트가 종료된 후에도 해당 변수가 사라지지않고 접근 가능한 현상
  • 클로저는 메모리 누수 문제가 있으므로, 사용하지 않는 Closure는 null, undefined 할당하여 제거가 필요함
profile
함께 개선하는 개발자

0개의 댓글