JavaScript 변수

seul_velog·2021년 11월 28일
0

JavaScript

목록 보기
4/25
post-thumbnail
post-custom-banner

변수(Variable)란?

변수는 값의 위치(주소)를 기억하는 저장소이다. 값의 위치란 값이 위치하고 있는 메모리 상의 주소를 의미한다. 즉, 변수란 값이 위치하고 있는 메모리 주소에 접근하기 위해 사람이 이해할 수 있는 언어로 명명한 식별자(identifier)이다.
또, 변수는 값을 유지할 필요가 있을 때 사용하는데, 여기에 담겨진 값은 다른 값으로 바꿀 수 있다.

즉, 변수란 데이터를 담아두는 공간이며 프로그램에서 사용되는 데이터를 일정 기간 동안 기억하여 필요한 때에 다시 사용하기 위해 데이터에 고유의 이름인 식별자를 명시한 것이다.
변수는 마치 (사람이 쓰는 언어인) 자연어에서 대명사와 비슷한 역할을 한다.

  • 식별자 : 어떤 대상을 유일하게 식별할 수 있는 이름 (변수명, 함수명, 프로퍼티명, 클래스명 등이 있다.)
  • 변수명 : 변수에 명시한 고유한 식별자
  • 변수값 : 변수로 참조할 수 있는 데이터 값



1. JavaScript에서의 변수 명명규칙

❗️ 변수명을 통해 데이터의 의미를 명확히 할 수 있어 코드의 가독성이 좋아지는 효과가 있다.

  • 변수의 이름으로는 a,b,c,d와 같이 의미가 없어 다른 사람이 보기에 무슨 뜻인지 알기 힘든 이름 대신 변수의 존재 목적을 쉽게 이해할 수 있도록 의미있는 변수명을 지정하여야한다.
    예로 a대신 number(혹은 num)를 사용하면 숫자가 들어올 것을 예상할 수 있다. 그러므로 짧지만 구체적인 이름을 짓는 것이 좋다고 한다. 🧐

변수를 선언할 때 지어주는 이름(변수명)을 식별자(Identifier)라고 부르며 JavaScript에서 식별자는 몇 가지 규칙을 반드시 따라야 한다.

  • 숫자가 포함될 수 있다.
  • 알파벳이 포함될 수 있다.
  • $가 포함될 수 있다.
  • _(underscore)가 포함될 수 있다.
  • 영문자의 대소문자를 구분한다.

변수 명명 중 안되는 규칙

  • 숫자로 시작할 수 없다.

  • 띄어쓰기가 들어가면 안된다. 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



2. 변수의 선언

  • 변수는 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;


2-1. 변수의 중복 선언

  • var 키워드로 선언한 변수는 중복 선언이 가능하다. 다시 말해 변수를 중복 선언하면 에러없이 이전 변수의 값을 덮어쓰게 되고, 중복해 선언해도 에러가 발생하지 않는다.
  • ❗️주의할 점❗️
    : 만약 동일한 변수명이 선언되어 있는 것을 모르고 변수를 중복 선언했다면 의도치 않게 변수의 값을 변경하는 부작용을 발생시킨다. 따라서 변수의 중복 선언은 문법적으로 허용되지만 사용하지 않는 것이 좋다.
    ✍️ var 를 알고 문제점에 대해 이해한 다음, 비로소 let 을 공부하고 사용한다면 좋을 것 같다고 생각했다. 이전 파일들은 var를 사용한 코드가 많을테니까 var와 let을 비교해서 알면 향후에 더 도움이 될 것 같다. 😀
var yy = 1;
console.log(yy); // 1
// 변수의 중복 선언
var yy = 2;
console.log(yy); // 2


2-2. 동적 타이핑 (Dynamic Typing)

  • 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
  • ❗️❗️ ✍️ 이런 타입은 아이디어가 생겨서 빠른 프로토 타입을 제작할 때는 유연하게 진행할 수 있겠지만, 다수의 엔지니어들 혹은 규모있는 프로젝트를 만들 때는 이러한 다이내믹 타이핑 때문에 에러상황이 생길 수 있다는 점도 알아두어야 할 것이다!
    즉 JS는 런타임에서 타입이 정해지기 때문에 에러상황 발생 경우가 있을 수 있으며, 그래서 TypeScript(자바스크립트 위에 타입이 더 얹어진 것)가 나왔다고 한다..😅



3. 스코프(Scope, 유효범위)

Scope는 우리말로 번역하면 ‘범위’라는 뜻이다. 즉, 스코프란 ‘변수에 접근할 수 있는 범위’라고 할 수 있다.

  • 대부분의 프로그래밍 언어는 블록 레벨 스코프(Block-level scope)를 따르지만 자바스크립트는 함수 레벨 스코프(Function-level scope)를 따른다.

    👉 1) 함수 레벨 스코프(Function-level scope)
    함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.


    2) 블록 레벨 스코프(Block-level scope)
    모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.


  • 자바스크립트에서 스코프는 2가지 타입 'global(전역)'과 'local(지역)' 이 있다.

    1) 전역 스코프 (Global scope)
    코드 어디에서든지 참조할 수 있다.

    2) 지역 스코프 (Local scope or Function-level scope)
    함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.


  • 모든 변수는 스코프를 갖는다. 변수의 관점에서 스코프를 구분하면 다음과 같이 2가지로 나눌 수 있다.

    1) 전역 변수 (Global variable)
    전역에서 선언된 변수이며 어디에든 참조할 수 있다.

    2) 지역 변수 (Local variable)
    지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.

✍️ 스코프 파트는 막상 정리하려고 하니 다른 언어들 특징까지 비교하면서 봐서 그런지 잘 정리되지 않았던 파트중 하나였다. 이고잉님의 강의도 찾아봐야겠다.




4. 변수 선언 방식 (var, let, const)

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, constvar 와는 다르게 선언 단계와 초기화 단계가 분리되어 진행된다. 그래서 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생하는데, 변수가 아직 초기화 되지 않았기 때문이다.

  • 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
  • 위에 정리한 '중복선언' 부분과 관계있는 내용이다. var 키워드로는 동일한 이름을 갖는 변수를 중복해서 선언할 수 있었다. 하지만, let 키워드로는 동일한 이름을 갖는 변수를 중복해서 선언할 수 없다. 변수를 중복 선언하면 문법 에러(SyntaxError)가 발생한다.

(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

  • 이 둘의 차이점은 'immutable' 여부이다.
    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

profile
기억보단 기록을 ✨
post-custom-banner

0개의 댓글