변수는 값의 위치(주소)를 기억하는 저장소이다. 값의 위치란 값이 위치하고 있는 메모리 상의 주소를 의미한다. 즉, 변수란 값이 위치하고 있는 메모리 주소에 접근하기 위해 사람이 이해할 수 있는 언어로 명명한 식별자(identifier)이다.
또, 변수는 값을 유지할 필요가 있을 때 사용하는데, 여기에 담겨진 값은 다른 값으로 바꿀 수 있다.
▶ 즉, 변수란 데이터를 담아두는 공간이며 프로그램에서 사용되는 데이터를 일정 기간 동안 기억하여 필요한 때에 다시 사용하기 위해 데이터에 고유의 이름인 식별자를 명시한 것이다.
변수는 마치 (사람이 쓰는 언어인) 자연어에서 대명사와 비슷한 역할을 한다.
식별자
: 어떤 대상을 유일하게 식별할 수 있는 이름 (변수명, 함수명, 프로퍼티명, 클래스명 등이 있다.)변수명
: 변수에 명시한 고유한 식별자변수값
: 변수로 참조할 수 있는 데이터 값
❗️ 변수명을 통해 데이터의 의미를 명확히 할 수 있어 코드의 가독성이 좋아지는 효과가 있다.
변수를 선언할 때 지어주는 이름(변수명)을 식별자(Identifier)라고 부르며 JavaScript에서 식별자는 몇 가지 규칙을 반드시 따라야 한다.
변수 명명 중 안되는 규칙
숫자로 시작할 수 없다.
띄어쓰기가 들어가면 안된다. camelCase로 변수명을 만든다.
그래서 'let everybody coding'이 아니라 'let everybodyCoding'이라고 쓰는건데, 이것이 낙타 등처럼 구불한 모양이라서 camelCase라고 이름 지어졌다고 한다.
'예약어' 라는 자바스크립트에서 미리 쓰이는 단어들이 있다.
for, while, do, if, catch, try, finally, else, import, export, default, break, continue, case, switch, class, function, var, let, const
등이 있는데 외울 필요없이 위의 예약어를 쓰면 해석기에서 'Uncaught SyntaxError: unexpected token [예약어이름]' 경고창이 뜬다!
예약어 키워드 참고
ex) var foo; // valid var _bar123; // valid var $1234337; // valid var 7seven; // invalid (숫자가 포함될 수는 있지만 숫자로 시작해서는 안된다.) var function; // invalid
var
, let
, const
키워드를 사용하여 '선언
' 하고 할당 연산자를 사용해 값을 '할당
' 한다. 그리고 식별자인 변수명을 사용해 변수에 저장된 값을 '참조
' 한다.let myName = 'seul'; console.log(myName); //seul myName = 'hello'; console.log(myName); //hello
나는 'let' 이라는 키워드를 이용해서 'myName'라는 변수를 선언했다. 이를 선언함과 동시에 'seul'이라는 변수의 '값'을 할당한다.
그리고 'myName'라는 변수에 'hello'라는 '값'을 다시 할당하게 되면 콘솔창에는 hello라고 변경되어서 뜨게 된다.
✍️ 내가 이해한 것
어플리케이션을 실행하게되면 어플리케이션마다 쓸 수 있는 메모리가 할당(제한적)되어 진다. 여기서 'let'이라는 키워드를 이용해서 'myName'라는 변수를 적용하면 'myName'라는 변수가 가리키고 있는 메모리 어딘가에 'seul' 이라는 값을 저장하게 되는 것이다.
추후에 'myName'의 변수가 가리키는 곳에 다른 값(여기서는 hello)을 넣어서 저장할 수도 있다.
+) 하지만 코드가 복잡해지고 길어지면서 이 부분 때문에 간혹 에러가 뜰 수도 있으니, 최대한 바뀌지 않는다는 가정하에 작성을 한다면 const를 쓰는게 좋을 것 같다.🤔
참고) var score; // 변수의 선언 score = 80; // 값의 할당 score = 90; // 값의 재할당 score; // 변수의 참조 // 변수의 선언과 할당 var average = (50 + 100) / 2;
var
를 알고 문제점에 대해 이해한 다음, 비로소 let
을 공부하고 사용한다면 좋을 것 같다고 생각했다. 이전 파일들은 var를 사용한 코드가 많을테니까 var와 let을 비교해서 알면 향후에 더 도움이 될 것 같다. 😀 var yy = 1; console.log(yy); // 1 // 변수의 중복 선언 var yy = 2; console.log(yy); // 2
JavaScript는 동적타입언어 'Dynamically typed language'라고 불린다.
JAVA나 C언어는 'Statically typed language' 즉, 변수를 선언할 때 어떤 타입인지 결정해서 타입을 같이 선언했던 반면, JavaScript는 선언할때 어떤 타입인지 선언하지 않고 런타임, 즉 프로그램이 동작할 때 할당된 값에 따라서 타입이 변경될 수 있다는 것을 얘기한다.
ex)
var foo;
console.log(typeof foo); // undefined
foo = null;
console.log(typeof foo); // object
foo = {};
console.log(typeof foo); // object
foo = 3;
console.log(typeof foo); // number
foo = 3.14;
console.log(typeof foo); // number
foo = 'Hi';
console.log(typeof foo); // string
foo = true;
console.log(typeof foo); // boolean
Scope는 우리말로 번역하면 ‘범위’라는 뜻이다. 즉, 스코프란 ‘변수에 접근할 수 있는 범위’라고 할 수 있다.
👉 1) 함수 레벨 스코프(Function-level scope)
함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.
2) 블록 레벨 스코프(Block-level scope)
모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
1) 전역 스코프 (Global scope)
코드 어디에서든지 참조할 수 있다.
2) 지역 스코프 (Local scope or Function-level scope)
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.
1) 전역 변수 (Global variable)
전역에서 선언된 변수이며 어디에든 참조할 수 있다.
2) 지역 변수 (Local variable)
지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.
✍️ 스코프 파트는 막상 정리하려고 하니 다른 언어들 특징까지 비교하면서 봐서 그런지 잘 정리되지 않았던 파트중 하나였다. 이고잉님의 강의도 찾아봐야겠다.
4-1. var 의 문제점
❓ 대부분의 프로그래밍 언어에서는 변수를 선언한 다음 값을 할당한다. 하지만, JS의 'var'에서는 선언 하기도 전부터 값을 할당해도 에러가 뜨지 않는다. 그 이유는 무엇일까?
(1) 변수 호이스팅(Variable Hoisting)
: 호이스팅(Hoisting, 끌어올리다)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다. (어디에 선언했냐에 상관없이 항상 제일 위로 선언을 끌어 올려준다.)
// var의 경우 ▼ console.log(foo); // undefined var foo; // let의 경우 ▼ console.log(bar); // Error: Uncaught ReferenceError: bar is not defined let bar;
: var의 경우, 변수 foo는 아직 선언되지 않았으므로 에러가 발생할 것을 예상했지만, 콘솔에는 undefined가 출력된다.
: let의 경우, 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
❗️❗️ " 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다." 라고 하는데..🧐 ?
❓ 여기서 내가 궁금했던 건, 👉 let이랑 const도 호이스팅 되는데…? var랑 뭐가 달라??
▶ 위의 예제를 보면 let
으로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다. 즉, TDZ에 들어가 있어서 참조 에러 나는 것!
❓ 이게 무슨 말일까?
✍️
var
키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 즉 스코프에 변수를 등록(선언단계)하고 메모리에 변수를 위한 공간을 확보한 후 undefined로 초기화 한다. 그래서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라한다.
하지만let, const
는var
와는 다르게 선언 단계와 초기화 단계가 분리되어 진행된다. 그래서 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생하는데, 변수가 아직 초기화 되지 않았기 때문이다.
let, const
변수의 선언 단계와 초기화 단계 사이를 일시적 사각 지대 (Temporal Dead Zone; TDZ)라고 부른다.- 실제 코드에서
let
변수의 선언 또는const
변수의 선언 및 할당 (const 의 경우 선언과 동시에 값 할당이 되어야 한다)이 나오기 전까지는 해당 변수는 TDZ에서 관리 한다고 생각하면 된다고 한다.- 해당 코드가 나오기 전에 미리 사용을 하려고 할 경우 TDZ에서 ReferenceError를 발생 시키는 것이다.
📌 추가)
호이스팅은 변수 선언이 스코프의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 말한다.
var
의 또 다른 문제들도 있다.
(2) 블록 레벨 스코프(Block-level scope)를 따르지 않는다.
즉 블럭을 철저히 무시하는데, block안에 변수를 선언했음에도 불구하고 콘솔을 이용해서 밖에서 변수를 출력하면 정상적으로 출력된다.
❗️아무리 깊은 곳에 블럭을 이용해서 변수를 선언해도 어디에서나 출력할 수 있다는 것은 👉 초창기에는 유연하게 썼겠지만, 후에 이것 때문에 중간중간 알 수 없게 선언된 값들이 툭툭 튀어나오는 결과를 초래했다고 한다.
(3) 변수 중복 선언
// var의 경우 ▼ var foo = 123; var foo = 456; // 중복 선언 허용 // let의 경우 ▼ let bar = 123; let bar = 456; // Uncaught SyntaxError: Identifier 'bar' has already been declared
(4) var 키워드 생략 허용
ex1.) var a = 5; b = 10; console.log(a + b); //15 ex2.) name = 'Evan' // 상기 코드는 var name = 'Evan' // 과 같다
- ex1.) 코드에서 var 키워드를 적지 않아도 변수로 선언되는 특징을 가지고 있다. 하지만 이렇게 될 때 나중에 문제를 일으킬 수도 있다.
ex2.) 변수 선언 키워드를 사용하지 않으면 var 키워드를 사용한 것으로 취급되기 때문에 무조건 써줘야 한다.
4-2. let과 const
let의 경우 ▼
let name = 'seul'
console.log(name) // seul
let name = 'javascript'
console.log(name) // Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name) //react
const의 경우 ▼
const name = 'seul'
console.log(name) // seul
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.
❗️ 이와 같기 때문에 기존의 var
대신 ES6에 추가된 let
을 사용하는 것이 좋다.
즉, 기본적으로는 의도치 않은 재할당을 방지해 줄 수 있는const
를 사용하고, 재할당이 필요한 경우에 한정해 let
을 사용하는 것이 좋다고 한다. 😀
reference
MDN Zerocho - Variable Data type & Variable - PoiemaWeb dreamcoding coding everybody