2022-09-26 TIL

김재훈·2022년 9월 28일
0

TIL

목록 보기
4/7

추가로 배워야 하거나 정리할 내용들

  • 블록 레벨 스코프와 함수 레벨 스코프
    (2022-09-20에 추가됨)
  • 모던 자바스크립트 Deep Dive의 프로토타입 파트까지 학습 후 프로토타입 기반 프로그래밍에 대한 설명글 작성
    (2022-09-20에 추가됨)

'모던 자바스크립트 Deep Dive' 학습

8장 제어문

  • 문의 종료에는 세미콜론을 붙이는 것이 일반적이지만, 불록문의 끝은 자체 종결성을 띄므로 세미콜론을 붙이지 않습니다.

9장 타입 변환과 단축 평가

  • 자바스크립트에서는 기본적으로 엔진이 값을 평가해 타입을 유추하며, 이 과정에서 암묵적으로 타입을 변환하기도 합니다.
  • 자바스크립트 엔진이 문자열 타입 아닌 값을 문자열 타입으로 암묵적 타입 변환하는 예제입니다.
// JS 엔진이 문자열 타입 아닌 값을 문자열 타입으로 변환하는 예제 모음

// 숫자 타입
0 + ''              // -> '0'
-0 + ''             // -> '0'
1 + ''              // -> '1'
-1 + ''             // -> '-1'
NaN + ''            // -> 'NaN'
Infinity + ''       // -> 'Infinity'
-Infinity + ''      // -> '-Infinity'

// 불리언 타입
true + ''           // -> 'true'
false + ''          // -> 'false'

// null 타입
null + ''           // -> 'null'

// undefined 타입
undefined + ''      // -> 'undefined'

// 심벌 타입
(Symbol()) + ''     // -> TypeError: Cannot convert a Symbol value to a string

// 객체 타입
({}) + ''           // -> "[object Object]"
Math + ''           // -> "[object Math]"
[] + ''             // -> ""
[10, 20] + ''       // -> "10,20"
(function(){}) + '' // -> "function(){}"
Array + ''          // -> "function Array() { [native code] }"
  • 숫자 타입 아닌 값을 숫자 타입으로 변환하는 예제입니다.
// 숫자 아닌 값을 숫자 타입으로 변환

// 문자열 타입
+''             // -> 0
+'0'            // -> 0
+'1'            // -> 1
+'string'       // -> NaN

// 불리언 타입
+true           // -> 1
+false          // -> 0

// undefined 타입
+undefined      // -> NaN

// 심벌 타입
+Symbol()       // -> TypeError: Cannot convert a Symbol value to a number

// 객체 타입
+{}             // -> NaN
+[]             // -> 0
+[10, 20]       // -> NaN
+(function(){}) // -> NaN
  • 불리언 타입 아닌 값을 불리언 타입으로 변환하는 경우 JS는 참/거짓을 Truthy, Falsy 값으로 구분하여 평가합니다. 특정 타입들은 Falsy 값이고 그 외에 값들은 모두 Truthy 값으로 판별하며, 그 예제는 아래와 같습니다.
// 전달 받은 인수가 Falsy 값이면 true, Truthy 값이면 false를 반환
function isFalsy(v) {
    return !v;
}

// 전달 받은 인수가 Truthy 값이면 true, Falsy 값이면 false를 반환
function isTruthy(v) {
    return !!v;
}

// Falsy 값인 타입들
isFalsy(false);
isFalsy(undefined);
isFalsy(null);
isFalsy(0);
isFalsy(NaN);
isFalsy('');

// 그 외는 모두 Truthy 값
isTruthy(true);
isTruthy('0'); // 빈 문자열이 아닌 모든 문자열은 Truthy 값
isTruthy({});
isTruthy([]);
  • 암묵적 타입 변환은 개발자 의도와 다르게 동작할 여지가 있으므로, 때로는 가독성을 위해 명시적으로 타입 변환을 해야 할 수 있습니다.
// 문자열 타입으로 변환
// 1. String 생성자 함수를 new 연산자 없이 호출
String(1);          // -> "1"
String(NaN);        // -> "NaN"
String(Infinity);   // -> "Infinity"
String(true);       // -> "true"
String(false);      // -> "false"

// 2. Object.prototype.toString 메서드 사용
(1).toString();         // -> "1"
(NaN).toString();       // -> "NaN"
(Infinity).toString();  // -> "Infinity"
(true).toString();      // -> "true"
(false).toString();     // -> "false"



// 숫자 타입으로 변환
// 1. Number 생성자를 new 연산자 없이 호출
Number('0');        // -> 0
Number('-1');       // -> -1
Number('10.53');    // -> 10.53
Number(true)        // -> 1
Number(false)       // -> 0

// 2. parseInt, parseFloat 함수를 사용(문자열->숫자만 가능)
parseInt('0');          // -> 0
parseInt('-1');         // -> -1
parseFloat('10.53');    // -> 10.53



// 불리언 타입으로 변환
// 1. Boolean 생성자 함수를 new 연산자 없이 호출
Boolean('x');           // -> true
Boolean('');            // -> false
Boolean('false');       // -> true
Boolean(0);             // -> false
Boolean(1);             // -> true
Boolean(NaN);           // -> false
Boolean(Infinity);      // -> true
Boolean(null);          // -> false
Boolean(undefined);     // -> false
Boolean({});            // -> true
Boolean([]);            // -> true

// 2. 부정 논리 연산자를 두 번 사용
!!'x';                  // -> true
!!'';                   // -> false
!!'false';              // -> true
!!0;                    // -> false
!!1;                    // -> true
!!NaN;                  // -> false
!!Infinity;             // -> true
!!null;                 // -> false
!!undefined;            // -> false
!!{};                   // -> true
!![];                   // -> true
  • 논리합(||), 논리곱(&&) 연산자는 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환하며, 이 특성을 이용해 if문을 대체할 수 있습니다. 이를 단축평가라고 합니다.
// 1. 논리곱(&&)으로 if문 대체
var done = true;
var message = '';

// 주어진 조건이 true일 때
if (done) message = '완료';

// 단축 평가
message = done && '완료';
console.log(message); // 완료



// 2. 논리합(||)으로 if문 대체
var done = false;
var message = '';

if (done) message = '미완료';

message = done || '미완료';
console.log(message); // 미완료
  • 단축 평가가 유용한 패턴을 살펴보며, 어떤 때에 이를 사용해야 하는지 예제와 함께 학습했습니다.
  • 객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때
// 객체를 가리키기를 기대하는 변수의 값이 객체가 아니라 null이나 undefined인 경우 타입 에러가 발생하며 프로그램이 강제 종료됨
var elem = null;
var value = elem.value; // TypeError: Cannot read property 'value' of null

// 단축 평가를 사용하면 타입 에러를 피할 수 있음
var elem = null;
// elem이 Falsy(null, undefined 같은) 값이면 elem으로 평가되고,(즉 객체를 가리키지 않는 변수 자체로 평가)
// Truthy 값, 즉 올바르게 객체를 가리키고 있는 경우 elem.value로 평가
var value = elem && elem.value; // -> null
  • 함수 매개변수에 기본값을 설정할 때
// 단축 평가를 사용하지 않은 경우
function weakGetStringLength(str) {
    return str.length;
}

console.log(weakGetStringLength()); // TypeError: Cannot read properties of undefined



// 단축 평가를 사용하여 위에서 발생한 문제 해결
function getStringLength(str) {
    // 단축 평가를 사용해 인수가 없을 때 매개변수에 undefined가 되는 상황을 방지
    str = str || '';

    return str.length;
}

getStringLength();          // -> 0
getStringLength('hi');      // -> 2



// ES6부터는 매개변수의 기본값을 설정하는 방법으로 undefined를 방지할 수도 있음
function es6GetStringLength(str = '') {
    return str.length;
}
es6GetStringLength();       // -> 0
es6GetStringLength('hi');   // -> 2
  • 옵셔널 체인 연산자: ES11에 도입된 기능으로 연산자 ?.는 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어갑니다.
var elem = null;

// elem이 null이기 때문에 undefined를 반환
var value = elem?.value;
console.log(value); // undefined



var str = '';

// 빈 문자열은 Falsy 값으로 논리곱의 경우 평가 결과가 Falsy 값이면 좌항을 그대로 반환하기 때문에, 문자열의 길이를 참조할 수 없음
var length = str && str.length;
console.log(length); // ''

//옵셔널 체인 연산자는 null 또는 undefined만 아니라면 개발자의 의도대로 동작함
var length = str?.length;
console.log(length); // 0
  • null 병합 연산자: ES11에 도입된 기능으로 연산자 ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환, 그렇지 않으면 좌항의 피연산자를 반환(변수에 기본값을 지정할 때 유용)합니다.
// 좌측이 null이나 undefined가 아닌 단순한 빈 문자열이라면 그대로 출력하고 싶더라도, 논리합을 이용한 방식은 빈 문자열이 Falsy 값이므로 우항의 피연산자를 반환
var foo = '' || 'default string';
console.log(foo); // "default string"

// ?? 연산자를 이용하면 Falsy 값이 아닌 null 또는 undefined가 아닌 경우에만 좌항의 피연산자를 반환하도록 할 수 있음
var foo = '' ?? 'default string';
console.log(foo); // ""

10장 객체 리터럴

  • 자바스크립트는 객체 기반의 프로그래밍 언어로, 원시 값을 제외한 나머지 값 모두(함수, 배열, 정규 표현식 등)은 모두 객체입니다.
  • 원시 값은 변경 불가능한 값이지만 객체 타입의 값은 변경 가능한 값이며, 자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값이 될 수 있습니다.

    따라서 자바스크립트의 함수도 일급 객체이기 때문에 값으로 취급할 수 있습니다.
  • 책에서는 일급 객체에 대해 18장에서 추가로 다루며, 18.1절 도입부에 정의된 내용만 미리 참고했습니다.
    - 다음 조건을 만족하는 객체를 일급 객체라 함
    1. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다.
    2. 변수나 자료구조(객체, 배열 등)에 저장할 수 있다.
    3. 함수의 매개변수에 전달할 수 있다.
    4. 함수의 반환값으로 사용할 수 있다.
  • 프로퍼티 값이 함수일 경우는 일반 함수와 구분 짓기 위해 메서드라 부릅니다.
  • 객체 = 프로퍼티 + 메서드
    - 프로퍼티: 객체의 상태를 나타내는 값
    - 메서드: 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 동작(behavior)
  • 자바스크립트는 프로토타입 기반 객체지향 언어로서 클래스 기반 객체지향 언어와 달리 다양한 객체 생성 방법을 지원합니다.
    - 객체 리터럴
    - Object 생성자 함수
    - 생성자 함수
    - Object.create 메서드
    - 클래스(ES6부터 지원)
  • 객체 리터럴의 중괄호는 코드 블록을 의미하지 않습니다. 즉 값으로 평가되는 표현식이며 닫는 중괄호 뒤에 세미콜론을 붙입니다.
profile
개발하면서 새롭게 배운 내용, 시행착오한 내용들을 잊지 않기 위해 기록합니다.

0개의 댓글