JavaScript 예습 | [Deep Dive] 04장 ~ 05장
04장 변수
4.1 변수란 무엇인가
메모리
- 메모리 : 데이터를 저장할 수 있는 메모리 셀의 집합체
- 메모리 셀 : 크기는 1바이트(8bit), 컴퓨터는 메모리 셀 단위로 데이터를 저장하거나 읽는다.
- 메모리 주소 : 메모리 셀들은 고유의 메모리 주소를 가진다.
- 4GB = 4 x 10^9 = 4 x 2^30 = 2 ^ 32 = (2^4)^8, 즉 8자리 16진수 0xFFFFFFFF로 표현됨.
- 0x00000000 ~ 0xFFFFFFFF
- 메모리에 연산 하기 위한 값을 저장하고, 연산된 값을 저장할 수 있음
10 + 20 을 계산한 CPU
10 + 20 을 CPU가 연산하고, 연산 된 결과 30을 메모리에 저장해도 그 값 30을 재사용 할 수 없음!
왜?
30이 저장된 메모리 공간에 직접 접근해야 하는데, 그 방법은 치명적인 오류를 발생시킬 수 있는 매우 위험한 일임.
만약 운영체제가 사용하고 있는 메모리에 접근하여 값을 바꿀 수 있다면, 시스템을 멈추게 하는 치명적인 오류가 발생할 수 있음.
따라서 자바스크립트에서는 개발자의 직접적인 메모리 제어를 허용하지 않음.
또한 만약 직접적인 메모리 제어가 가능하더라도, 값이 저장될 메모리 주소는 임의로 정해지기 때문에, 연산을 실행할 때 마다 저장될 메모리 주소는 변하게 된다. 그래서 코드가 실행되기 전에는 메모리 주소를 알 수 없고, 알려 주지도 않는다.
변수 Valuable
하나의 값을 저장하기 위해 확보한 메모리 공간 자체, 또는 그 메모리 공간을 식별하기 위해 붙인 이름.
값의 위치를 가리키는 상징적인 이름.
따라서 위처럼 메모리 공간 주소로 직접 접근하지 않고, 아래와 같이 변수를 통해서 메모리 공간에 저장된 값을 사용할 수 있게 된다.
- 변수 이름 : resulte
- 변수 값 : 30
- 할당 assignment : 변수에 값을 저장
- 참조 reference : 참조
4.2 식별자
- 식별자 identifier : 어떤 값을 구별해서 식별할 수 있는 고유한 이름.
- 변수 이름, 함수 이름, 클래스 이름 ...
- 식별자는 값이 아니라 메모리 주소를 기억하고 있다.
- 선언 declaration : 선언으로 자바스크립트 엔진에 식별자 존재를 알림.
4.3 변수 선언 variable declaration
- 변수를 생성하는 것
- 값을 저장하기 위한 메모리 공간을 확보(allocate)하고 변수 이름과 확보된 메모리 공간의 주소를 연결(name binding)해서 값을 저장할 수 있게 준비하는 것
- 확보가 해제(release)되기 전까지는 누구도 확보된 메모리 공간을 사용할 수 없음.
변수를 사용하려면 반드시 선언이 필요함
var, let, const 키워드를 사용
- ES5 : var 만 존재
- ES6 : let, const 추가
- 선언: 변수 이름을 등록해 자바스크립트 엔진에 변수의 존재를 알림
var a; // 선언
undefined는 자바스크립트에서 제공하는 원시 타입의 값(primitive value)임.
undefined가 들어가는 이유는, 변수에 값이 할당되기 전에 변수에 접근하면, 기존 메모리에 저장되어 있는 쓰레기 값(garbage value)을 참조하게 될 수 있음. 따라서 그런 의미없는 값을 사용자가 참조하기 전에, undefined로 값을 초기화 하지 않았다는 것을 알려주어 배려하는 것임.
- 변수의 호이스팅 variable hoisting
변수 선언은 소스코드 어디에 있든 상관 없이 다른 코드보다 먼저 실행한다.
변수 선언이 소스코드가 순차적으로 실행되는 런타임 이전 단계에 먼저 실행된다.
console.log(a); // undefined
var a; // 선언
따라서 위와 같이 변수 선언 이전에 변수를 참조하면, 변수 선언이 호이스팅 되어 error가 아닌 undefined가 출력됨.
변수 선언 뿐 아니라 모든 식별자는 호이스팅 됨.
4.5 값의 할당 assignment
변수에 값을 할당(대입, 저장)할 때는 할당 연산자 = 을 사용함.
우변의 값을 좌변의 변수에 할당함
var score; // 변수 선언
score = 80; // 값 할당
위와 같이 선언과 할당은 다음과 같이 하나의 문(statement)으로 단축 표현 할 수 있음.
var score = 80; // 변수 선언과 값의 할당
선언 된 자리에 값을 지우고, 그 자리에 값을 할당하지 않는다!
새로운 메모리 주소를 변수와 연결하고, 그 메모리에 값을 할당한다.
굳이 새로운 메모리 주소를 확보하는 이유는 아래와 같다.
var a=1;
var b=a;
// 여기까진 a랑 b가 가리키는 메모리 주소가 같음
a=2;
// 여기서 b는 기존의 a가 가리키던 주소를 가리킴
// a는 새로운 메모리공간에 2를 저장하고 그 주소를 가리킴
console.log(b); // 1
console.log(a); // 2
a값만 변경하고 싶은데, b값도 같이 변경 되는 것을 막기 위해, 값이 할당되면 아예 새로운 메모리를 확보하는 것!
https://junwoo45.github.io/2019-11-04-memory_model/
<번역>자바스크립트의 메모리 모델
이 글은 Ethan Nam의 JavaScript's Memory Model을 번역한 글입니다.
junwoo45.github.io
[JS] 불변값과 가변값
불변값 (Immutable Value)
medium.com
- 선언 vs 할당 시점
- 런타임 이전: 변수 선언
- 런타임: 값 할당
*런타임: 소스코드가 순차적으로 실행되는 시점
console.log(score); // undefined
score = 80; // 할당
var score; // 선언
console.log(score); // 80
변수 선언문 var score;은 코드 상단으로 호이스팅 된다.
런타임 때 첫 번째 console.log에서는 할당 이전이므로 undefined가,
두 번째 console.log는 할당 이후이므로 80이 출력됨.
4.6 값의 재할당
var score = 80; // 변수 선언과 값의 할당
score = 90; // 값의 재할당
var 키워드로 선언한 변수는 값을 재할당 할 수 있음.
재할당은 현재 변수에 저장된 값을 버리고 새로운 값을 저장하는 것.
사실 var 키워드로 선언과 동시에 undefined로 초기화 되기 때문에, 변수에 처음으로 값을 할당하는 것도 재할당임.
재할당은 변수에 저장된 값을 다른 값으로 변경함.
상수 : 값을 재할당할 수 없음. 단 한번만 할당할 수 있는 변수.
재할당의 경우 할당과 마찬가지로 기존의 메모리가 아닌 새로운 메모리 주소를 확보하여 값을 저장함.
- 가비지 콜렉터 garbage collectoer
애플리케이션이 할당(allocate)한 메모리 공간을 주기적으로 검사하여 더이상 사용되지 않는 메모리를 해제(release)하는 기능을 말함.
더 이상 사용되지 않는 메모리 = 어떤 식별자도 참조하지 않는 메모리 공간
메모리 누수(memory leak)을 방지함.
- 언매니지드 언어, 매니지드 언어
- 언매니지드 언어
C언어 처럼 개발자가 명시적으로 메모리를 할당하고 해제하기 위해 malloc(), free()같은 저수준 메모리 제어 기능을 가지는 언어.
개발자의 역량에 따라 최적의 성능을 확보할 수 있지만, 그 반대의 경우 치명적 오류를 생산할 수 있음
- 매니지드 언어
메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당하고, 개발자는 메모리 제어를 하지 못함.
더 이상 사용하지 않는 메모리의 해제는 가비지 콜렉터가 수행하고, 이 부분도 개발자가 관여할 수 없다.
일정한 생산성을 확보할 수 있는 장점이 있지만, 성능에서 손실은 감수할 수 밖에 없다.
4.7 식별자 네이밍 규칙
식별자 네이밍 규칙
- 식별자는 특수문자를 제외한 문자, 숫자, (_), ($)를 포함할 수 있음
- 단, 숫자로 시작하는 것은 허용하지 않는다
- 예약어는 식별자로 사용할 수 없음.
다음은 잘못된 식별자
var first-name; // SyntaxError: Unexpected token -
var 1st; // SyntaxError: Invalid or unexpected token
var this; // SyntaxError: Unexpected token this
네이밍 컨벤션 naming convention
다음과 같은 4가지 유형의 네이밍 컨벤션이 존재함.
// 카멜 케이스 (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 옵저버블
- 카멜 : 변수나 함수
- 파스칼 : 생성자 함수, 클래스 이름
5장 표현식과 문
5.1 값 value
값은 식이 평가되어 생성된 결과.
평가란 식을 해석해서 값을 생성하거나 참조하는 것
// 10 + 20 은 평가되어 숫자 값 30을 생성함
10 + 20; // 30
모든 값은 데이터 타입을 가지며, 메모리에 2진수 즉 비트의 나열로 저장된다.
ex) 메모리에 저장된 0100 0001
- 숫자 : 65
- 문자 : 'A'
타입에 따라 다르게 해석될 수 있다.
- 변수 : 하나의 값을 저장하기 위해 확보한 메모리 공간 자체
따라서 변수에 할당되는 것은 값이다.
// 변수에 10 + 20이 평가되어 생성된 숫자 값 30이 할당된다.
var sum = 10 + 20;
5.2 리터럴 literal
사람이 이해할 수 있는 문자
약속된 기호를 사용해 값을 생성하는 표기법(notation)
*사람이 이해할 수 있는 문자(아라비아 숫자, 알파벳, 한글...)
*미리 약속된 기호 ('', "", ., [], {}, //...)
// 정수 리터럴 3
3
// 부동소수점 리터럴
10.5
// 2진수 리터럴
0b01000001
// 8진수 리터럴
0o101
// 문자 리터럴
'hello'
// 불리언 리터럴
true
false
// null 리터럴
null
// undefined 리터럴
undefined
// 객체 리터럴
{ name: 'Lee', address: 'seoul' }
// 배열 리터럴
[1, 2, 3]
// 함수 리터럴
function() {}
// 정규 표현식 리터럴
/[A-Z]+/g
자바스클비트 엔진은 코드가 실행되는 시점인 런타임에 리터럴을 평가해 값을 생성한다.
즉 리터럴은 값을 생성하기 위해 미리 약속한 표기법임.
5.3 표현식 expression
표현식은 값으로 평가될 수 있는 문(statement)임.
표현식이 평가되면 새로운 값을 생성하거나 기존값을 참조함.
리터럴은 값으로 평가되어, 리터럴도 표현식임
var score = 100; // 100은 리터럴. 표현식임
var score = 50 + 50; // 50+50도 평가되어 값 100이 되므로 표현식임
score; // 100. 식별자를 참조하면 변수 값으로 평가되므로 표현식임.
즉 값으로 평가될 수 있는 문은 모두 표현식이다.
// 리터럴 표현식
10
'Hello'
// 식별자 표현식 => 선언이 이미 존재할 때
sum
person.name
arr[1]
// 연산자 표현식
10 + 20
sum = 20
sum !== 20
// 함수,메서드 호출 표현식 => 선언이 이미 존재한다고 가정
square()
person.getName()
표현식은 값처럼 사용할 수 있음.
var x = 1 + 2;
// 식별자 표현식 x는 숫자 값 3처럼 사용 가능
x + 3; // 6
5.4 문 statement
프로그램을 구성하는 기본 단위이자 최소 실행 단위.
- 프로그램: 문의 집합으로 이뤄진 것
- 프로그래밍: 문을 작성하고 순서에 맞게 나열
토큰 token
문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미
문은 여러 토큰으로 구성됨.
ex) 키워드, 식별자, 연산자, 리터럴, 세미콜론, 마침표, ...
var sum = 1 + 2;
// 토큰: var, sum, =, 1, +, 2, ;
- 문은 명령문
컴퓨터에서 내리는 명령어.
문이 실행되면 명령이 실행되고 무슨 일이 일어남.
ex) 선언문, 할당문, 조건문, 반복문, ...
5.6 표현식인 문과 표현식이 아닌 문
표현식은 문의 일부일 수 있고, 그 자체로 문이 될 수 있다.