변수라는 것은 프로그램을 짤 때, 알고리즘을 표현하기 위해서 꼭 필요한 존재입니다.
프로그래밍에서 데이터를 저장하고 관리하기 위해 사용되며, 프로그램이 실행되는 동안 값이 계속 바뀌거나 유지되어야 하는 경우, 이를 효율적으로 다루기 위해 변수가 필요합니다
변수를 선언하려면 선언자를 붙여서 변수를 선언합니다.
var 변수; // undefined
할당 값 없이 변수만 선언할 경우, str이라는 변수에는 할당된 값이 없기 때문에 "정의되지 않은" 상태의 타입인 undefined가 들어갑니다.
변수에 값을 할당하려면 대입 연산자를 사용하여 할당합니다.
var 변수이름 = 할당할 값
// ex:
var num = 100;
var animals = ["🐶", "🐱", "🐵"];
var dog = { name: "Pet", age: 13, gender: "male" };
...
ECMAScript 6부터는 var
로 선언했을때의 단점을 보완한 let
과 const
라는 변수 선언자가 추가되었습니다.
var cake = "🎂";
var cake = "🍰";
하지만 이때 중복으로 선언된 변수는 마지막 변수가 모든 중복된 변수를 덮어씌우기 때문에 마지막에 할당한 값인 조각케이크(🍰)가 출력됩니다.유효범위가 전체이기 때문에 선언 전에 접근이 가능합니다(호이스팅).
var
라는 선언자는 좋게 말하면 자유롭습니다. 선언한 위치 전체가 유효범위가 됩니다.
함수바깥에서 선언한 경우 프로그램의 전체가 유효범위가 되고, 함수안에서 선언했다면 지역 변수가 되어 함수 내 전체가 유효범위가 됩니다.
⚡️ 호이스팅이란?
호이스팅이란 것은 선언부가 유효범위의 상단으로 끌어올려지기 때문에, 선언 전에 변수를 사용 및 참조 할 수 있게 됩니다.
- 선언 전에 변수를 사용할 수 있습니다.
- 선언 전에 ReferenceError를 던지지않고 변수를 참조 할 수 있습니다. 대신 값은 항상
undefined
입니다.- 선언 전의 범위에 영향을 줄 수 있습니다.
- 선언의 부수 효과는 해당 선언을 포함하는 코드의 나머지를 평가하기 전에 발생합니다.
MDN - Hoisting
console.log(dog); // undefined
var dog = "🐶"
console.log(dog); // 🐶
// dog 변수가 호이스팅되어 상단으로 끌어올려짐
var dog;
// 선언만 됐으므로 undefined가 됨.
console.log(dog);
var dog = "🐶"
console.log(dog);
이러한 특징들 때문에 뜻하지 않은 버그를 발생 시킬 수 있고, 혼란을 줄 수 있습니다.
이 때문에 let
과 const
가 탄생하며 조금 더 안전하게 코드를 작성 할 수 있게 됩니다.
중복으로 선언하지 못합니다. (문법에러가 발생합니다.)
let dog = "🐶";
let dog = "🐕🦺";
// Uncaught SyntaxError: Identifier 'dog' has already been declared
let
과 const
는 유효범위가 선언된 위치의 "전체 범위"인 var
과 다르게 블록 유효 범위를 갖습니다. 또, 선언한 범위에 Temporal Dead Zone(일시적 사각지대)이 생깁니다. 따라서, 선언 전에는 사용 및 참조를 하지 못합니다.
// var
function varFunc () {
console.log(cat);
var cat = "🐱";
return cat;
}
varFunc();
// undefined
// 🐱
// let / const
function letConstFunc () {
console.log(cat);
let cat = "🐱";
return cat;
}
letConstFunc();
// Uncaught ReferenceError: Cannot access 'cat' before initialization
여기서! 호이스팅이 안된다고 할 수는 없는 경우가 있습니다.
const monkey = "🐵";
{
console.log(monkey);
const monkey = "🦧";
}
// Uncaught ReferenceError: Cannot access 'unicorn' before initialization
const
는 블록유효 범위를 가집니다. 따라서 위 코드에서는 블록안에서 monkey를 출력하려고 할때 상위 스코프에 있는 monkey(🐵)를 출력해야 할 것 같은데, 그렇지 않고 에러를 발생 시킵니다.
이는 const로 선언된 변수가 있을 때 Temporal Dead Zone을 만드는 것처럼, 선언된 스코프를 '오염'시키기 때문에 블록내에서 아직 초기화 되지 않은 monkey(🦧)를 가져오면서 에러를 던지게 됩니다.
let
은 초기값 없이 일단 변수만 선언할 수 있습니다.
let cat;
let carrot, apple;
...
const
는 반드시 값을 넣어 초기화를 해야합니다.
// ✅
const cat = "meow";
// ❌
const cat; // Uncaught SyntaxError: Missing initializer in const declaration
let
은 한번 선언한 변수에 다른 값을 재할당할 수 있습니다.
let i = 0;
while(i < 3) {
i += 1;
console.log(i);
};
// 1
// 2
// 3
const
는 상수의 의미이기 때문에 한번 선언한 변수에 다른 값을 재할당할 수 없습니다.
const i = 0;
while(i < 3) {
i += 1;
console.log(i);
};
// Uncaught TypeError: Assignment to constant variable.
⚡️
const
로 선언한 값이 객체인 경우
const
로 선언한 값이 객체인 경우에는 마찬가지로 완전히 새롭게 재할당 하는것은 안되지만, 객체의 프로퍼티는 수정할 수 있습니다.// ✅ const animals = ["🐭", "🐮", "🐯", "🐇", "🐲"]; animals.push("🐍") console.log(animals); // ["🐭", "🐮", "🐯", "🐇", "🐲", "🐍"];
// ❌ const animals = ["🐭", "🐮", "🐯", "🐇", "🐲"]; animals = ["🐭", "🐮", "🐯", "🐇", "🐲", "🐍"]; // Uncaught TypeError: Assignment to constant variable.
함수를 선언하는 방식으로는 함수 선언식 말고도 함수 표현식이 있습니다.
변수에 함수를 할당하는 방식이며 함수 리터럴로 할당을 할 수 있습니다.
// 함수 선언문
function sayMeow () {
console.log("meow");
};
또는 화살표 함수로 할당할 수도 있습니다.
// 익명함수를 sayMeow라는 변수에 할당
const sayMeow = function() {
console.log("meow");
};
// 화살표 함수
const sayMeow = () => {
console.log("meow");
};
함수 선언문은 이전에 언급했던 var
키워드로 선언한 변수와 동일하게 호이스팅이 되지만, 함수 표현식의 경우 호이스팅이 되지 않습니다.
변수에 함수를 할당하는 것이기 때문에 변수에 할당하고 나서야 함수는 그 변수의 이름을 가지게 되며, 해당 이름으로 호출 할 수 있게 됩니다.
sayMeow(); // Uncaught ReferenceError: sayWaffle is not defined
const sayMeow = function () {
console.log("meow");
}