제 자신의 공부를 위하여 제가 알기 쉽도록 기록한 것입니다.
공식문서와 다를 수 있습니다.
//예제 코드
var name = 'zero'; // (1)변수 선언 (6)변수 대입
function wow(word) { // (2)변수 선언 (3)변수 대입
console.log(word + ' ' + name); // (11)
}
function say () { // (4)변수 선언 (5)변수 대입
var name = 'nero'; // (8)
console.log(name); // (9)
wow('hello'); // (10)
}
say(); // (7)
처음 코드를 실행하는 순간 모든것을 포함하는 전역 컨텍스트가 생깁니다.
모든 것을 관리하는 환경이며, 페이지가 종료될 때까지 유지됩니다.
전역 컨텍스트 말고 함수 컨텍스트도 있는데,
함수를 호출 할 때마다 함수 컨텍스트가 하나씩 더 생깁니다.
컨텍스트의 4가지 원칙은 아래와 같습니다.
전역 컨텍스트가 생성된 후 두번째 원칙에 따라 변수객체,스코프체인,this가 생성 됩니다.
전역 컨텍스트는 arguments 가 없고, variabled은 해당 스코프의 변수들 이다.
전역 컨텍스트': {
변수객체: {
arguments: null,
variable: ['name', 'wow', 'say'],
},
scopeChain: ['전역 변수객체'],
this: window,
}
wow 랑 say 는 호이스팅 때문에 선언과 동시에 대입이 되며,
그 후 variable의 name 에 'zero' 가 대입됩니다.
variable: [{ name: 'zero' }, { wow: Function }, { say: Function}]
그 후 say(); 를 하는 순간 새로운 say 함수 컨텍스트가 생성됩니다.
arguments 는 없고, variable은 name 뿐입니다.
스코프 체인은 say 변수 객체와 상위의 전역 객체입니다.
this는 설정해 준 적이 없으니 window를 가져갑니다.
'say 컨텍스트': {
변수객체: {
arguments: null,
variable: ['name'], // 초기화 후 [{ name: 'nero' }]가 됨
},
scopeChain: ['say 변수객체', '전역 변수객체'],
this: window,
}
이렇게 반복하여, 다음 wow 함수를 실행하여, wow 컨텍스트가 생깁니다.
wow 함수 종료 후 wow 컨텍스트가 사라지고, say 함수의 실행이 마무리 되면서
say 컨텍스트가 사라지며, 마지막에 전역 컨텍스트도 사라지게 됩니다.
호이스팅이란 ?
변수를 선언하고 초기화했을 때, 선언 부분이 최상단으로 끌어올려지는 것을 의미합니다.
console.log(name);//undefined
sayHi(); // 'Hi'
function sayHi(){
console.log('Hi');
}
let name ='kim'
위 sayHi 처럼 함수 표현식이 아닌 함수 선언식일 경우는
함수 선언식 자체가 통째로 끌어 올려집니다.
sayWow(); // (3)
sayYeah(); // (5) 여기서 대입되기 전에 호출해서 에러
var sayYeah = function() { // (1) 선언 (6) 대입
console.log('yeah');
}
function sayWow() { // (2) 선언과 동시에 초기화(호이스팅)
console.log('wow'); // (4)
}
위 처럼 함수 표현식의 경우, 에러가 발생합니다.
위 코드를 실행 시 처음에 전역 컨텍스트가 생성 되는데
아시다시피 컨텍스트 생성 및 코드는 순차적으로 실행됩니다.
sasyYeah 는 대입되기전에 호출되어 에러가 발생하겠네요.
여기서 (5)번을 TDZ(Temporal Dead Zone) 이라고 합니다.
전역 컨텍스트': {
변수객체: {
arguments: null,
variable: [{ sayWow: Function }, 'sayYeah'],
},
scopeChain: ['전역 변수객체'],
this: window,
}
변수를 선언 및 초기화 하기전에 호출하여 나타나는 사각지대 의 개념이다.
let makeClosure = function() {
let name = 'zero';
return function () {
console.log(name);
}
};
let closure = makeClosure(); // function () { console.log(name); }
closure(); // 'zero';
closure 함수 안에 console.log(name)이 있는데요.
name은 closure 함수의 매개변수도 아니고, closure 함수 내부에서 생성한 변수도 아닙니다.
바로 이런 것이 비공개 변수입니다.
function() { console.log(name) }은 name 변수나, name 변수가 있는 스코프에 대해 클로저라고 부를 수 있습니다.
클로져는 실전에서 겪어보면서 배우는게 제일 빠를듯 합니다.