변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름
선언 : 변수를 실행 컨텍스트의 변수 객체에 등록한다. 이 변수 객체는 스코프가 참조하는 대상
초기화 : 변수 객체에 등록된 변수를 위해 메모리 공간을 확보, 암묵적으로 undefined를 할당해 초기화
할당 : undefined로 초기화된 변수에 실제 값을 할당
* es6에서 let, const 추가
변수 선언은 선언 → 초기화단계
를 거쳐 수행
var kmj
console.log(kmj) // output: undefined
console.log(kmj) // output: undefined
var kmj
위의 경우 둘다 undefined이 반환되지만 후자의 경우 변수선언이 런타임이 아니라 이전 단계에서 실행된다
변수선언이 어디에 있던 다른 코드보다 먼저 실행되는데 이를 호이스팅
이라고 한다
var kmj // 변수 선언
kmj = 'howdy-mj' // 값의 할당
var kmj = 'howdy-mj' // 변수 선언과 할당
변수 선언은 호이스팅 되어 런타임 이전에 실행
값의 할당은 런타임에 실행
// 1. 함수 선언문
// 함수 이름 생략 불가능
function add(x, y) {
return x + y
}
// 2. 함수 표현식
// 함수 이름 생략 가능
var add = function(x, y) {
return x + y
}
// 함수 이름 작성 시,
// var add = function plus(x, y) {
// return x + y
// }
// 3. Function 생성자 함수
var add = new Function('x', 'y', 'return x+ y')
// 4. 화살표 함수
var add = (x, y) => x + y
함수가 정의되는데는 위와 같이 4가지 방식이 있다
// 함수 참조
console.dir(add) // output: f add(x, y)
console.dir(sub) // output: undefined
// 함수 호출
console.log(add(2, 5)) // output: 7
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function
// 함수 선언문
function add(x, y) {
return x + y
}
// 함수 표현식
var sub = function(x, y) {
return x + y
}
함수선언문의 경우 런타임이전에 실행됨으로 호이스팅 시킬 수 있다
함수표현식은 런타임에서 할당되어 객체가 되기때문에 런타임 이전에는 undefined로 초기화 시킨다
- 변수 중복 선언이 가능 (예기치 못한 값을 반환할 수 있다)
- 함수 레벨 스코프로 인해 함수외부에서 선언한 변수는 모두 전역변수
(var 생략 시 암묵적 전역 변수 양산)- 변수 선언문 이전에 변수를 참조하면 언제나 undefined를 반환
(변수 호이스팅)
변수 중복 선언 불가, 재할당은 가능
let name = 'kmj'
console.log(name) // output: kmj
let name = 'howdy' // output: Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'howdy'
console.log(name) // output: howdy
변수 중복 선언 불가, 재할당도 불가
재할당의 경우, 원시 값은 불가능하지만, 객체는 가능 (불변을 의미하지 않는다)
let과 다른 점은 선언과 초기화를 동시에 진행
const name; // output: Uncaught SyntaxError: Missing initializer in const declaration
const name = 'kmj'
// 원시값의 재할당
const name = 'kmj'
name = 'howdy' // output: Uncaught TypeError: Assignment to constant variable.
// 객체의 재할당
const name = {
eng: 'kmj',
}
name.eng = 'howdy'
console.log(name) // output: { eng: "howdy" }
let, const는 블록 레벨 스코프를 따른다
let a = 1
if (true) {
let a = 5
}
console.log(a) // output: 1
var 을 사용하는 경우 5를 출력하지만, let으로 선언한 경우 전역에 있는 값을 출력
선언과 초기화단계가 분리되어 진행
선언이 런타임이전에 실행되지만, 초기화 되기 전에 변수에 접근하면 참조에러가 뜬다
console.log(name) // output: Uncaught ReferenceError: name is not defined
let name = 'kmj'
선언과 초기화를 동시에 진행
console.log(name) // output: Uncaught ReferenceError: Cannot access 'name' before initialization
const name = 'kmj'
기본적으로 변수의 스코프는 최대한 좁게 만드는 것을 권장한다
따라서, var 키워드 보다는 let과 const 키워드를 사용하며,
변경하지 않는 값(상수)이라면 let 보다는 const 키워드를 사용하는 것이 안전하다.