개발자 연쨘

[딥 다이브]변수 본문

스터디/모던 자바스크립트 Deep Dive

[딥 다이브]변수

연쨘 2023. 11. 30. 01:39
 

 

 


 

변수란? 🐰

 

변수값의 위치(주소)를 기억하는 저장소이다.

값의 위치란 값이 위치하고 있는 메모리 상의 주소를 의미한다.

즉, 변수란 값이 위치하고 있는 메모리 주소에 접근하기 위해

사람이 이해할 수 있는 언어로 명명한 식별자이다.

식별자는 어떤 대상을 유일하게 식별할 수 있는 이름.
식별자에는 변수명, 함수명, 프로퍼티명, 클래스명등이 있음.

변수랑 식별자는 같은게 아닌가?! 🐯
변수와 식별자는 프로그래밍에서 중요한 개념이지만 서로 다른 의미를 가지고 있음.

-변수 (Variable):
변수는 데이터를 저장하고 나중에 사용하기 위한 메모리 위치를 가리키는 이름
예를 들어, 숫자나 문자열과 같은 데이터를 저장할 때 사용
프로그램에서 변수는 값을 보관하고 해당 값을 변경할 수 있습니다.
컴퓨터 용어로서의 변수는 '변할 수 있는 데이터'를 의미한다.

- 식별자 (Identifier): 식별자는 변수, 함수, 클래스 등과 같은
프로그램 요소를 구별하는 데 사용되는 이름. 즉, 변수명이다.
식별자는 변수의 이름, 함수의 이름 등을 지칭. 식별자는 특정 규칙을 따라야 하며,
예를 들어, 문자로 시작하고 문자, 숫자, 언더스코어(_)로 이루어져야 함



변수와 식별자 예시 🐯

//변수와 식별자
var b; 
// 변할 수 있는 데이터를 만든다. 이 데이터의 식별자는 b로 한다.

 

즉, 변수란 변경 가능한 데이터가 담길 수 있는 공간 또는 그릇을 뜻하며 그 공간의 이름이 식별자이다.


변수는 varletconst 키워드를 사용하여 선언하고 할당 연산자를 사용해 값을 할당한다.

그리고 식별자인 변수명을 사용해 변수에 저장된 값을 참조한다.

 

변수에 여러 개의 값을 저장하는 방법  ✨

변수는 하나의 값을 저장하기 위한것, 여러 개의 값을 저장하려면 여러개의 변수를 사용해야함.

단, 배열이나 객체 같은 자료구조를 사용하면 관련이 있는 여러 개의 값을 그룹화해서 하나의 값으로 사용 가능!

// 변수는 하나의 값을 저장하기 위한 수단이다.
var userId = 1;
var userName = 'Lee';

// 객체나 배열 같은 자료구조를 사용하면 여러 개의 값을 하나로 그룹화해서 하나의 값처럼 사용할 수 있다.
var user = { id: 1, name: 'Lee' };

var users = [
  { id: 1, name: 'Lee' },
  { id: 2, name: 'Kim' }
];
//예제 04-02

 


var result = 10 + 20;

 

변수 result에는 10+20이라는 연산을 하기 위해

10과 20이 메모리 상의 임의의 위치에 저장되고

CPU는 이 값을 읽어 연산을 수행한다.

 

연산 결과로 생성된 숫자 값 30 또한 메모리 상의 임의의 위치에 저장된다.

이때 메모리 공간에 저장된 값 30을 다시 읽어 들여 재사용할 수 있도록

저장된 메모리 공간에 상징적인 이름을 붙임!(=변수명)

 

 

 

사람을 고유한 이름으로 구별하듯이 변수도 사람이 이해할 수 있는 언어로 지정한

고유한 식별자(변수명)에 의해 구별하여 참조할 수 있다.

데이터는 메모리에 저장되어 있다.

메모리에 저장된 데이터를 참조하려면 데이터가 저장된 메모리 상의 주소를 알아야 한다.

식별자(변수이름)는 데이터가 저장된 메모리 상의 주소를 기억한다.

따라서 식별자를 통해 메모리에 저장된 값을 참조할 수 있다.

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

 

*참조 : 변수에 저장된 값을 읽어 들이는 것.

 


 

식별자 🐰

 

변수 이름을  식별자라고도 한다.

식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말함.

값은 메모리 공간에 저장되어 있다.

식별자는 값이 아니라 메모리 주소를 기억하고 있다.

 

식별자로 값을 구별해서 식별한다는 것의 의미는

식별자가 기억하고 있는 메모리 주소를 통해 메모리 공간에 저장된 값에 접근할 수 있다는 의미!

즉, 식별자는 메모리 주소에 붙인 이름!

 

다시 말하지만 식별자는 값을 나타내는게 아니라

저장된 값의 메모리 주소를 기억하는것!

더보기

* 변수이름(식별자)는 실행 컨텍스트에 등록됨.

실행 컨텍스트는 자바스크립트 엔진이 소스코드를 평가하고

실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역.

변수이름과 변수 값은 실행 컨텍스트 내에 키/값 형식인 객체로 등록되어 관리된다.


식별자 네이밍 규칙

  • 반드시 영문자(특수문자 제외), underscore ( _ ), 또는 달러 기호($)로 시작하여야 한다.
    이어지는 문자에는 숫자(0~9)도 사용할 수 있다. (예약어는 사용할 수 없다.)
  • 자바스크립트는 대/소문자를 구별하므로 사용할 수 있는 문자는 “A” ~ “Z” (대문자)와 “a” ~ “z” (소문자)이다.

예제로 설명하는 식별자 네이밍

var person, $elem, _name, first_name, val1;

 

위예시와 같이 식별자는 쉼표로 구분해 하나의 문에서 여러 개를 한번에 선언 가능 !

하지만 가독성이 나빠지므로 권장하지 않음

 

var first-name; // SyntaxError: Unexpected token –
var 1st;        // SyntaxError: Invalid or unexpected token
var this;       // SyntaxError: Unexpected token this

var first-name; ▶ underscore는 가능하지만 - 이 기호는 식별자 네이밍에 사용하지 못함.
var 1st;        ▶  첫번째에 숫자가 올 수 없음
var this;      ▶ 예약어를 식별자명에 사용할 수 없음

 

var firstname;
var firstName;
var FIRSTNAME;

자바스크립트는 대소문자를 구별하기 때문에 영문은 같더라도

세개 다 다른 식별자이다.

 

var x = 3;       // NG. x 변수가 의미하는 바를 알 수 없다.
var score = 100; // OK. score 변수는 점수를 의미한다.

// 경과 시간. 단위는 날짜다
var d;                 // NG

var elapsedTimeInDays; // OK

변수는 존재 목적을 쉽게 이해할 수 있도록 의미를 명확히 표현해야한다.

또한 변수 선언에 별도의 주석이 필요하다면 좋지못한 변수이다.

 

// 카멜 케이스 (camelCase)
var firstName;

// 스네이크 케이스 (snake_case)
var first_name;

// 파스칼 케이스 (PascalCase)
var FirstName;

// 헝가리언 케이스 (typeHungarianCase)
var strFirstName; // type + identifier
var $elem = document.getElementById('myId'); // DOM 노드
var observable$ = fromEvent(document, 'click'); // RxJS 옵저버블

네이밍 컨벤션 :

하나 이상의 영어 단어로 구성된 식별자를 만들 때 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 규칙

 

자바스크립트에서는 일반적으로

변수나 함수에는 카멜 케이스

생성자 함수, 클래스 이름에는 파스칼 케이스

코드 전체의 가독성을 높이려면 카멜 케이스와 퍼스칼 케이스를 따르는 것이 유리함


 

변수 선언과 호이스팅 🐰

 

변수 선언이란 변수를 생성하는 것을 의미.

메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를

연결해서 값을 저장할 수 있게 준비하는 것.

모든 선언문은 한 줄씩 실행되는시점인 런타임이 아닌 그 이전 단계에서 먼저 실행됨.

 

변수를 사용하려면 반드시 선언이 필요하다.

변수를 선언할 때는 var, let, const 키워드를 사용한다.

(let과 const는 ES6에서 도입됨)

var score; // 변수 선언(변수 선언문)

위예제에서는 변수를 선언은 하였지만 값은 할당하지 않았다.

따라서 변수 선언에 의해 확보된 메모리 공간은 비어있을거라 생각하겠지만

undefined라는 값이 암묵적으로 할당되어 초기화된다.

 

호이스팅 ✨

변수가 어떻게 생성되며 호이스팅이 되는 과정은 3단계에 걸쳐 생성된다.


선언 단계(Declaration phase)
변수 객체(Variable Object)에 변수를 등록한다.
이 변수 객체는 스코프가 참조하는 대상이 된다.



초기화 단계(Initialization phase)
변수 객체(Variable Object)에 등록된 변수를 메모리에 할당한다.
이 단계에서 변수는 undefined로 초기화된다.



할당 단계(Assignment phase)
undefined로 초기화된 변수에 실제값을 할당한다.

 

var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.

즉, 스코프에 변수가 등록되고 변수는 메모리에 공간을 확보한 후 undefined로 초기화된다.

따라서 변수 선언문 이전에 변수에 접근하여도 Variable Object에 변수가 존재하기 때문에 에러가 발생하지 않는다.

다만 undefined를 반환한다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라한다.

이후 변수 할당문에 도달하면 비로소 값의 할당이 이루어진다.

//var foo; //호이스팅되어 변수 선언이 끌어올려짐
console.log(foo); // ① undefined
var foo = 123;
console.log(foo); // ② 123
{
  var foo = 456;
}
console.log(foo); // ③ 456

 

①이 실행되기 이전에 var foo = 123;이 호이스팅되어

①구문 앞에 var foo;가 옮겨진다.

(실제로 변수 선언이 코드 레벨로 옮겨진 것은 아니고

변수 객체(Variable object)에 등록되고 undefined로 초기화된 것이다.)

 

하지만 변수 선언 단계와 초기화 단계가 할당 단계와 분리되어 진행되기 때문에

이 단계에서는 foo에는 undefined가 할당되어 있다.

 

변수 foo에 값이 할당되는 것은 2행에서 실시된다.

에서는 변수에 값이 할당되었기 때문에 123이 출력된다.

 

자바스크립트의 변수는 블록 레벨 스코프(block-level scope)를 가지지 않고

함수 레벨 스코프(function-level scope)를 갖는다.

단, ECMAScript 6에서 도입된 let, const 키워드를 사용하면 블록 레벨 스코프를 사용할 수 있다. 

 

-> 코드 블록 내의 변수 foo는 전역변수이므로

전역에 선언된 변수 foo에 할당된 값을 재할당하기 때문에 ③의 결과는 456이 된다.


*함수 레벨 스코프 : 함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서 참조할 수 없음.

즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는

모두 전역 변수이다.

*블록 레벨 스코프 : 코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며

코드 블록 외부에서는 참조할 수 없다. 


 var을 쓰지말라고 어떤 단점때문에 쓰지 말라는걸까? ✍🏻

1. 함수 레벨 스코프
-전역 변수라서 변수의 변경이 발생할 수 있는 가능성 증가

2.중복 선언 허용

3.변수 호이스팅
-변수를 선언하기 전에 참조가 가능하다.

 

console.log(score); // undefined

var score = 80;     // 변수 선언과 값의 할당

console.log(score); // 80

var score = 80;은

var score; 변수 선언

score = 80; 값의 할당

이 되는 두개의 문이 하나의 문장으로 단축 표현된것.

 

 

위 그림처럼 변수 선언 할때 이전 값 undefined가 저장되어 있던 메모리 공간을 지우고

새로운 값을 할당하는게 아니라 새로운 메모리 공간을 확보하고 그곳에 할당값을 저장하는것을 기억하자!

 

 

값의 재할당 🐰

 

재할당은 현재 변수에 저장된 값을 버리고 새로운 값을 저장하는 것.

엄밀하게 말하면 변수는 선언과 동시에 undefined로 초기화되기 때문에

변수에 처음으로 값을 할당하는 것도 재할당임.

 

재할당은 변수에 저장된 값을 다른 값으로 변경하는건데

이렇게 변할 수 있기때문에 변수라고 불리는것이다!

값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없다면 ? 상수이다!
상수는 단 한 번만 할당할 수 있는 변수다.

 

var score;  // 변수 선언
score = 80; // 값의 할당

 

값이 재할당될때 같은 메모리 공간을 사용하는게 아니라 새로운 메모리 공간을 확보하고

그 메모리 공간에 저장하는것이다. 이점을 주의해서 기억하자.

값이 재할당 되어 전에 값을 안쓰게 된다면 불필요한 값으로 가비지 콜렉터에 의해

메모리에서 자동 해제 되지만 언제 해제될지는 예측 불가능하다.

 

* 가비지 콜렉터 : 자바스크립트는 가비지 콜렉터를 내장하고 있는 매니지드 언어이다.

메모리 공간을 주기적으로 검사하여 더 이상 사용되지 않는 메모리를 해제하는 기능을 한다.

728x90