const x=1;
function outerFunc(){
const x= 10;
function innerFunc(){
console.log(x); //10
}
innerFunc();
}
outerFunc();
<예제 1 - innerFunc 함수가 outerFunc 함수의 내부에 정의된 중첩함수인 경우>
const x=1;
function outerFunc(){
const x= 10;
innerFunc();
}
function innerFunc(){
console.log(x); //1
}
outerFunc();
<예제 2 - innerFunc 함수가 outerFunc 함수의 내부에 정의된 중첩함수가 아닌 경우>
예제1의 경우 innerFunc에서 outerFunc의 x변수에 접근 할 수 있으나 예제2에서는 접근할 수 없다. 이 같은 현상이 발생하는 이유는 자바스크립트가 렉시컬 스코프를 따르는 프로그래밍 언어이기 때문이다.
13.5절에서 렉시컬 스코프에 대해 위와같이 정의한 바 있다. 이를 다시 아래와 같이 정의할 수 있다.
const x =1;
//1.
function outer(){
const x =10;
const inner = function () {console.log(x);} // 2.
return inner;
}
//outer 함수를 호출하면 중첩 함수 inner를 반환한다.
//그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다.
const innerFunc = outer(); //3.
innerFunc(); // 4. 10
위 예제처럼 외부 함수(outer)보다 중첩 함수(inner)가 더 오래 유지되는 경우 중첩 함수는 이미 생명주기가 종료한 외부 함수의 변수(x)를 참조할 수 있다.
이러한 중첩 함수를 클로저라고 부른다.
//카운트 상태 변경 함수
const increase = function (){
// 카운트 상태 변수
let num =0;
//카운트 상태를 1만큼 증가
rturn ++num;
};
//이전 상태를 유지하지 못한다.
console.log(increase()); //1
console.log(increase()); //1
console.log(increase()); //1
//카운트 상태 변경 함수
const increase = function (){
// 카운트 상태 변수
let num = 0;
// 클로저
return function (){
//카운트 상태를 1만큼 증가시킨다.
rturn ++num;
};
}();
console.log(increase()); //1
console.log(increase()); //2
console.log(increase()); //3
캡슐화는 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다.
캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 하는데 이를 정보 은닉이라 한다.
자바스크립트는 public, private, protected같은 접근 제한자를 제공하지 않는다.
특정 패턴을 사용하면 정보 은닉이 가능한 것처럼 보이지만, 완전한 정보은닉을 지원하지는 못한다.
ES6의 Symbol또는 WeakMap을 사용하여 private한 프로퍼티를 흉내내기도 하였으나 근본적인 해결책이 되지는 못했다.
다행히도, 2021년 1월기준 private필드를 정의할수 있는 새로운 표준 사양이 제안 되었으며 이에 대해서는 25.7.4절 private필드 정의 제안에서 살펴보도록 할 것이다.