함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.
변수 선언과 할당 중 선언부만 호이스팅한다는 내용을 코드로 확인해보자
noDefine();
function noDefine() {
// 변수 선언 및 할당 이전에 호출 테스트
console.log("not defined : " + name);
var name = "ojava";
// 변수 초기화 이후 값 확인
console.log("defined : " + name);
}
위 코드의 결과를 예상해보면 첫번째 콘솔 로그에서 사용된 name은 선언되지 않았기 때문에 오류가 발생할 것 같지만, 오류 없이 아래와 같은 로그가 찍힌다.
not defined : undefined
defined : ojava
단, 이 경우 변수 선언하는 var를 생략하는 경우 예상치 않은 결과를 내뱉으므로 주의해야 한다.
noDefine 이라는 함수 범위의 변수를 생성하려했으나, name = "ojava"의 형태로 선언한 경우 이상한 결과가 반환된다.
noDefine();
function noDefine() {
console.log("not defined : " + name);
// var name = "ojava";
name = "ojava"; // 변수 선언 명령어 없이 name 변수에 할당함
console.log("defined : " + name);
}
not defined : ojava
defined : ojava
오류가 발생하지 않았을뿐 아니라, 변수를 할당하기 전임에도 이미 할당된 값으로 반환해버린다.
함수 내에서 변수 선언 명령어를 제외하고 선언 시 전역 변수의 형태로 사용됨에 주의하자!
이 경우는 함수에서 선언 명령어 없이 초기화 한 값을 전역 변수로 사용하고 있음을 볼 수 있으며, 예상하지 못한 결과값을 반환할 수 있으므로 주의해야 한다.
- 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
- 이는 let 로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.
하지만, var 로 선언된 변수와는 달리 let 로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
우선, var는 변수 선언 방식에 있어서 큰 단점을 가지고 있다.
var name = 'bathingape'
console.log(name) // bathingape
var name = 'javascript'
console.log(name) // javascript
변수를 한 번 더 선언했음에도 불구하고, 에러가 나오지 않고 각기 다른 값이 출력되는 것을 볼 수 있다.
그래서 ES6 이후, 이를 보완하기 위해 추가 된 변수 선언 방식이 let 과 const 이다.
위의 코드 선언을 let으로 바꾸면 에러가 뜬다!
const도 마찬가지로 재선언 해주면 에러가뜬다!
let name = 'bathingape'
console.log(name) // bathingape
let name = 'javascript'
console.log(name)
// Uncaught SyntaxError: Identifier 'name' has already been declared
let 은 변수에 재할당이 가능하다. 그렇지만,
let name = 'bathingape'
console.log(name) // bathingape
let name = 'javascript'
console.log(name)
// Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name) //react
const는 변수 재선언, 변수 재할당 모두 불가능하다.
const name = 'bathingape'
console.log(name) // bathingape
const name = 'javascript'
console.log(name)
// Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name)
//Uncaught TypeError: Assignment to constant variable.
무엇이 좋다고 확실하게 말하기 어려우나 상황에따라 좋은 방법은 있는 것 같다!
그리고 객체를 재할당하는 경우는 생각보다 흔하지 않다. const 를 사용하면 의도치 않은 재할당을 방지해 주기 때문에 보다 안전하다.
재할당이 필요한 경우에 한정해 let 을 사용한다. 이때, 변수의 스코프는 최대한 좁게 만든다.
재할당이 필요 없는 상수와 객체에는 const 를 사용한다.