
"자바스크립트는 참 특이한 친구다"
var a = 1;
var name = "안뇽";
var age = 27;
console.log(age);
라는 코드가 있다.
자바스크립트 엔진은 위 코드를 실행시키기 직전에 선언된 변수들이나 함수들을 한번 쓱 훑고는
메모리에 다 기억을 해둔다
그러다 어디서 a 라는 변수를 호출하면 메모리에 기억해둔 a 라는 변수를 퉤 하고 뱉어준다.
그거시 바로 "호이스팅"
조금 더 격식있게 표현해보자면
호이스팅이란?
함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에
선언하는 것을 말한다.
- 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다.
- 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
- 함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.
- 유효 범위: 함수 블록 {} 안에서 유효
- 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
- 실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.
- 실제 메모리에서는 변화가 없다.
조금 더 예를 들어보자
console.log(age);
var age = 27;
console.log(age);
이런 코드가 있다.
항상 코드는 위에서 아래로 흐른다.
java 나 c++ 같은 언어를 공부해봤다면 이런 생각이 들꺼다.
"아니 변수 선언 하기도 전에 변수를 가져다 쓰려고 하네 1번 라인에서 에러나겠네!"
"응 아니야"
결과는
undefined
27
이미 자바스크립트 엔진이 선언된 변수를 훑어서 기억하고 있는 상태가 된 뒤에 1번라인부터 시작하기 때문에 해당 변수를 사용 할 수는 있다.
또 호이스팅 시에 변수의 선언과 초기화를 같이 시켜버리기 때문에 값을 날려버린다.
이것이 바로 호이스팅
기존의 var 는 전역에서 썼던 지역에서 썼던 싹다 호이스팅 시켜버린다 (함수만 빼고)
전역변수는 그렇다 쳐도 지역변수까지 메모리에 올려버리면 너무 낭비다
그리고 문제 하나더 아래 코드를 보자
var age = 27
console.log(age);
var age = 30
console.log(age);
이거 말이 되는 코드일까?
자비로우신 자바스크립트는 이것마저 허용 해준다.
이것이 바로 var 의 문제점!!
let/const 을 쓰자
let/const 을 사용하면 위에 말이 안되는 코드들을 해결 할 수 있다.
바로 Temporal Death Zone(TDZ) 덕택이다.
let/const 도 호이스팅이 된다. 하지만 코드 라인에서 a 선언문이 나오기 전까진 a 변수에 접근할 수 없어 라고 해주는 거다.
둘다 TDZ 로 관리되지만 차이는 바로
"const 는 재할당 될 수 없어!"
const name = 'javascript';
console.log(name); // javascript
name = 'vue';
console.log(name);
// Uncaught TypeError: Assignment to constant variable ()
// BUT
let age = 20
age = 30
console.log(age); // 30
요런느낌
그리하여
const 를 기본으로 사용하여 불필요한 변수의 재사용을 방지하고,
재할당이 필요한 경우 let 을 사용하는 것이 좋겠다.
스코프란 유효한 참조 범위를 뜻하며,
기존의 방법인 var 로 선언한 변수와 let 또는 const 로 선언한 변수의 스코프는 다르다.
예를 들어보자
function func() {
if (true) {
let a = 5;
console.log(a); // 5
}
console.log(a); // ReferenceError: a is not defined
}
console.log(a); // ReferenceError: a is not defined
위에서 설명했듯이 {} 블록 내부에서 선언된 변수는 코드블록 내에서면 유효하다.
[개념]
클로저는 독립적인( 자유 ) 변수를 가르키는 함수이며,
생성될 때의 환경( Lexical environment )을 기억하다.
[활용]
외부에서 변수에 직접 접근을 제한할 수 있다. ( 은닉화 )
캡슐화 구현 가능
코드를 보자
function func(name) {
let _name = name;
return function(){
console.log('Hello i am :' + _name);
}
}
const hello1 = func("예준")
const hello2 = func("광현")
hello1(); // Hello i am : 예준
hello2(); // Hello i am : 광현
끝!! 그럼 다음시간에 만나요