[모던 자바스크립트 Deep Dive] 05-09장

Gyuwon Lee·2022년 7월 17일
0
post-thumbnail

42 서울의 모던 자바스크립트 Deep Dive 스터디 학습의 일환으로, 새롭게 알게 된 내용 중심으로 정리되어 있습니다.


CH05. 표현식과 문

1) 값

우리가 작성하는 대부분의, 정말 90% 이상의 코드는 어떤 '값'을 위해 작성된다. '값'이라는 용어가 당연히 전혀 낯설지는 않지만, 막상 설명하려 하면 난감할 수 있다.
이란 어떤 의미인가?

let foo = 10 + 20 // 30

표현식평가 되어 생성된 결과를 말한다. 표현식과 평가의 의미도 뒤에서 살펴볼 것이다. 간단히 평가 란, 식을 해석해서 값을 생성하거나 참조하는 것을 의미한다.

위 예제의 표현식( 이하 ) 은 평가 되어 숫자 30 을 생성한다. 모든 값들은 데이터 타입을 갖고 2진수 형태로 저장되며, 이 2진수는 데이터 타입에 따라 각기 다른 값으로 해석된다.

위 예제에서, 변수 foo 에 저장된 것은 10 + 20 이라는 이 아니라, 해당 이 평가된 결과인 30 이라는 이다.

은 다양한 방법으로 생성될 수 있는데, 가장 기본적인 방법은 리터럴 을 사용하는 것이다.


2) 리터럴

리터럴 이란, 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 말한다고 한다. 간단히 말해 컴퓨터나 엔진이 아니라 '프로그래머가 이해할 수 있는 언어로 짜인 대부분의 코드'를 의미한다.

let foo = 10 + 20 // 숫자 리터럴 10과 20을 연산해 값 30이 생김
let bar = 30; // 숫자 리터럴 30이 바로 평가되어 값 30이 됨

위 예제에서, 변수 bar 와 같이 단 하나의 숫자도 리터럴 이 될 수 있다. 자바스크립트 엔진은 그 숫자를 평가해 데이터 타입을 갖고 2진수의 형태인 30을 만들어내는 것이다.

즉 리터럴은 컴퓨터가 이해할 수 있는 값 이전에 사람이 이해할 수 있는 문자 또는 미리 약속된 기호로 표기한 코드다. 자바스크립트 엔진은 런타임에 이 리터럴평가 하여 을 생성한다. 리터럴은 그 자체로 표현식 이다.


3) 표현식

let x = 1 + 2 // 1 + 2는 평가되어 값 3이 된다.
x + 3 // 6으로 평가된다. 1 + 2와 그 값인 3인 동치이기 때문.

표현식 이란 값으로 평가될 수 있는 문이다. 즉 표현식평가 되면, 새로운 을 생성하거나 기존 값을 참조한다. 앞서 살펴본 리터럴 역시 엔진에 의해 값으로 평가된다고 했으므로, 이 역시 표현식이다.

기억해둘 점은, 표현식이 평가된 값과 표현식은 동등한 관계, 즉 동치라는 점이다. 따라서 자바스크립트에서 표현식은 값처럼 사용할 수 있다. 즉, 문법적으로 값이 위치할 수 있는 자리에는 표현식도 위치할 수 있다.

따라서 표현식은 다른 표현식의 일부가 되어 새로운 값을 만들어낼 수도 있다.


4) 문

이란 프로그램을 구성하는 기본 단위이자 최소 실행 단위다. 문과 표현식의 차이를 구분하기는 모호한 부분들이 있다. 예를 들어, var sum = 1 + 2 는 하나의 문이다. 다만 그 안에서 var sum 역시 변수를 선언하는 하나의 (변수 선언문) 이다.

이렇듯 문은 표현식의 상위 개념으로, 표현식인 문표현식이 아닌 문으로 나뉜다. 이 둘을 구분하는 간단한 방법으로는 변수에 할당해 보는 것이 있다.

앞서 표현식 은 값으로 평가되어, 그 평가된 값과 표현식 자체는 동치라고 했으므로 표현식인 상태에서 변수에 할당 역시 가능하다고 했다. 그러나 표현식이 아닌 문 은 값으로 평가할 수 없으므로 변수에 할당하면 에러가 발생한다.

의 종료를 나타내는 기호로는 ; 을 사용하고, { } 코드블록 역시 문의 종료를 의미하는 자체 종결성을 지닌다는 점에 유의하면 코드를 읽을 때 의미 단위를 나누는 데 있어 이해도를 높일 수 있을 것이다.


CH06. 데이터 타입

1) 자바크스크립트의 7가지 데이터 타입

number

C나 자바의 경우, 정수와 실수 등 숫자를 구분해서 int, long, double 등 여러 숫자 타입을 제공한다. 하지만 자바스크립트는 단 하나의 숫자 타입만 존재하며 모든 수를 실수로 처리한다.

또한 2진수, 8진수, 16진수를 표현하기 위한 데이터 타입을 제공하지 않기 때문에, 이들 값을 참조하면 모두 10진수로 해석된다.

let binary = 0b01000001;
let octal = 0o101;
let hex = 0x41;

// 저장된 형태는 각기 다르지만, 모두 10진수 '65'로 출력된다.
console.log(binary);
console.log(octal);
console.log(hex);

string

일반적으로 '작은따옴표' 로 텍스트를 감싸서 표현한다.

자바스크립트에서는 문자열이 원시 타입이며, 변경 불가능한 값이다.반면 C에서는 문자의 배열로 문자열을 표현하기 때문에 동일한 메모리 주소를 가진 채로 특정 글자에 접근해서 변경하는 것이 가능하다.

따옴표 대신 백틱 으로 텍스트를 감싸는 템플릿 리터럴 방식을 사용할 수도 있다. 이 표기법은 편리한 문자열 처리 기능들을 제공한다:

  • 멀티라인 문자열 (이스케이프 시퀀스 없이 줄바꿈 가능)
  • 표현식 삽입 ( ${} 내부에 표현식 입력 )
    • 이때 표현식의 평가 결과가 문자열이 아니더라도, 문자여롤 타입이 강제 변환되어 삽입된다.

boolean, undefined, null

  • boolean : 논리적 참 거짓. truefalse
  • undefined : undefined 가 유일하다. 일반적으로 변수가 선언된 이후 값이 할당된 적이 없음을 나타내는 예약어로 사용되며, 프로그래머가 명시적으로 할당하지는 않는 것이 권장된다.
  • null : 변수에 값이 없음을 의도적으로 명시할 때 사용된다. 즉 이전에 할당되어 있던 값에 대한 참조를 명시적으로 제거하는 것이다. 참조가 제거되어 남겨진 값은 자바스크립트 엔진에 의해 가비지 콜렉션으로 수거될 것이다. 한편으로는 함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null 을 반환하기도 한다.

symbol

변경 불가능한 원시 타입의 값으로, 다른 값과 중복되지 않는 유일무이한 값이다.

symbol 이외의 원시 값들은 리터럴을 통해 생성하지만, symbol 은 반드시 Symbol 함수를 호출해 생성한다. 이렇게 생성된 심벌 값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값이다.

let key = Symbol('key');
console.log (typeof key); // symbol

let obj = {};
obj[key] = 'value';
console.log(obj[key]); // value

객체 타입

자바스크립트를 이루고 있는 거의 모든 것은 객체다. 위의 6가지 원시 타입 이외에 배열, 함수 등 모든 값은 모두 객체 타입이다.

동적 타이핑

자바스크립트의 변수에는 어떤 데이터 타입의 값이라도 자유롭게 할당될 수 있다. 값을 할당하는 시점에 변수의 타입이 동적으로 결정되고, 이후에도 타입을 자유롭게 변경할 수 있다.

즉, 자바스크립트에서는 선언이 아닌 할당에 의해 변수의 타입이 결정된다. 그리고 재할당에 의해 이 타입은 언제든지 동적으로 변할 수 있다. 엄밀히 말하자면 변수가 타입을 갖는 것이 아니라, 값이 타입을 가지기 때문에 값에 의해 변수의 타입이 동적으로 결정된다고 보는 것이 적절하다.


CH07. 연산자

|| : 첫 번째 truthy 를 찾는 OR 연산자

result = value1 || value2 || value3;

위와 같은 코드에서 OR || 연산자는 다음 순서에 따라 연산을 수행한다:

  • 가장 왼쪽 피연산자부터 시작해 오른쪽으로 나아가며 피연산자를 평가
  • 각 피연산자를 불린형으로 변환
  • 변환 후 그 값이 true 면 연산을 멈추고, 해당 피연산자의 변환 전 원래 값을 반환
  • 피연산자 모두를 평가한 경우( = 모든 피연산자가 false 로 평가되는 경우 )엔 마지막 피연산자를 반환

여기서 핵심은 반환 값이 형 변환을 하지 않은 원래 값이라는 것이다. 즉, OR || 연산자를 여러 개 체이닝(chaining) 하면 첫 번째 truthy 를 반환한다. 피연산자에 truthy 가 하나도 없다면 마지막 피연산자를 반환한다.

이런 OR 연산자의 추가 기능은 여러 용도로 활용된다.

1. 변수 또는 표현식으로 구성된 목록에서 첫 번째 truthy 얻기

OR || 을 사용하면 실제 값이 들어있는 변수를 찾고, 그 값을 보여줄 수 있다.

let firstName = "";
let lastName = "";
let nickName = "김별명";

alert( firstName || lastName || nickName || "익명"); // 김별명

2. 단락 평가(short circuit evaluation)

OR || 은 왼쪽부터 시작해서 오른쪽으로 평가를 진행하는데, truthy 를 만나면 나머지 값들은 건드리지 않은 채 평가를 멈춘다. 이런 프로세스를 '단락 평가’라고 한다.

단락 평가의 동작 방식은 두 번째 피연산자가 변수 할당과 같은 부수적인 효과(side effect)를 가지는 표현식 일 때 명확히 볼 수 있다.

true || alert("not executed");
false || alert("executed");

위 예시를 실행하면 두 번째 메시지만 출력된다.

첫 번째 줄의 || 연산자는 true 를 만나자마자 평가를 멈추기 때문에 alert 가 실행되지 않는다.

단락 평가는 연산자 왼쪽 조건이 falsy 일 때만 명령어를 실행하고자 할 때 자주 쓰인다.

&& : 첫 번째 falsy 를 찾는 AND 연산자

AND 연산자의 작동 방식은 OR 연산자의 작동 방식과 유사하다. 차이점은 AND 연산자가 첫 번째 falsy 를 반환하는 반면, OR 은 첫 번째 truthy 를 반환한다는 것이다.

즉, AND 연산자는 첫 번째 falsy 를 반환한다. 피연산자에 falsy 가 없다면 마지막 값을 반환한다.

활용 역시 OR 연산자와 유사한 방식으로, 변수 또는 표현식으로 구성된 목록에서 첫 번째 falsy 를 얻거나 연산자 왼쪽 조건이 truthy 일 때만 명령어를 실행하고자 할 때 사용된다.

💡 null, undefined 와 비교


  • null은 대소 비교 시에 숫자 0 값으로 암묵적인 타입 변환이되고, 동등 비교시에는 타입 변환이 되지 않는다.
console.log(null >= 0); // true
console.log(null > 0); // false
console.log(null == 0); // false
  • undefined는 대소 비교 시에 NaN 으로 타입이 변환된다.
console.log(undefined > 0); // false
console.log(undefined < 0); // false
console.log(undefined == 0); // false



CH08. 제어문

switch

switch 문의 표현식 값과 case 문은 일치 ( === )하는 경우에만 실행흐름을 옮긴다.

아래 코드의 경우 표현식의 값이 arg = 4 이지만 case 문의 arg < 5true 값을 가지기 때문에 default 문이 실행된다.

arg = 4;
switch (arg) {
  case arg < 5:
    console.log("5 미만입니다.");
    break;

  default:
    console.log("알 수 없는 값입니다.");
}

레이블 문 : 중첩 for 문 탈출

중첩 for문에서, 외부 for 문을 탈출하려면 레이블 문을 사용한다.

// 외부 for 문에 레이블 outer 를 지정, 
// break 문에 이 레이블 식별자 outer 를 지정
outer: for (var i = 0; i < 3; i++) {
  for (var j = 0; j < 3; j++) {
    // 원래 내부 for 문의 break 는 오직 내부 for 문만 탈출시킨다.
	// 그러나 여기서는 i + j가 2가 되는 순간 모든 외부 for 문을 탈출할 수 있게 된다.
    if (i + j === 2) break outer;
    console.log('inner valid');
  }
}

조건문에서 배열의 처리

선언된 배열은 빈 배열이라도 true 값으로 간주된다.

배열은 참조 자료형이기 때문에, 변수는 그 배열이 들어 있는 메모리 주소를 저장하고 있다. 따라서 배열이 채워져 있는지 여부와는 관계없이, 할당된 순간 그 변수는 가리킬 값(메모리 주소)를 갖고 있으므로 true 값으로 평가된다.

const arr = [];

if (arr) {
  console.log(arr); // []
}

arr.push(1);

if (arr) {
  console.log(arr); // [1]
}

CH09. 타입 변환과 단축 평가

옵셔널 체이닝 연산자와 null 병합 연산자

?. : 옵셔널 체이닝 연산자

좌항이 null 또는 undefined이 면 undefined 를 반환하고, 그렇지 않으면 우항의 프로퍼티 값을 참조한다.

?? : null 병합 연산자

좌항이 null 또는 undefined 이면 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.

profile
하루가 모여 역사가 된다

0개의 댓글