타입 변환과 단축 평가

</>·2021년 10월 31일
3
post-thumbnail

목표

  • 9장의 내용을 최대한 이해하고 정리하기

9장 타입 변환과 단축 평가

9-1. 타입 변환이란 무엇인가?

  • 타입 변환을 하는 방법에는 두 가지가 있다.
  • 개발자가 의도적으로 값의 타입을 변환하는 것을 명시적 타입 변환 또는 타입 캐스팅(type casting)이라고 한다.
var number = 10;
console.log(typeof number);
var str = number.toString();
console.log(typeof str);


// 결과
number
string
  • 개발자의 의도와 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환하는 것을 암묵적 타입 변환 또는 타입 강제 변환(type coercion)이라고 한다.
var number = 10;
console.log(typeof number);
var str = number + '';
console.log(typeof str);

// 결과
number
string
  • 명시적 타입 변환이나 암묵적 타입 변환이 기존 원시 값(위의 예에선 number)을 직접 변경하는 것은 아니다. 원시 값은 변경 불가능한 값이기 때문에 변경할 수 없고 새로운 원시 값을 생성한다.
  • 이처럼, 기존 원시 값을 사용해서 다른 타입의 새로운 원시 값을 생성하는 것을 타입 변환이라고 한다.

위의 두 종류의 타입 변환을 자세히 살펴보자.

9-2. 암묵적 타입 변환

  • 암묵적 타입 변환은 자바스크립트 엔진이 표현식을 평가할 때 개발자의 의도와 상관없이 암묵적으로 데이터 타입을 변환하는 것을 말한다.
  • 암묵적 타입 변환이 발생하면 문자열, 숫자, 불리언과 같은 원시 타입 중 하나로 타입을 자동 변환한다.

9-2-1. 문자열 타입으로 변환

var exp = 1 + "2";
console.log(typeof exp);

//결과
string
  • 위의 식에서는 피연산자 중 하나 이상이 문자열이므로 문자열 연결 연산자로 동작한다.
  • 따라서, 자바스크립트 엔진은 위의 식을 평가하기 위해 피연산자 중 문자열이 아닌 피연산자를 암묵적으로 타입을 변환한다.
var exp = `1 + 1 = ${1 + 1}`
console.log(typeof exp);

//결과
string
  • ES6에서 도입된 템플릿 리터럴도 마찬가지이다. ${ }를 사용한 표현식 삽입은 평가 결과를 문자열 타입으로 암묵적 타입 변환한다.

9-2-2. 숫자 타입으로 변환

console.log(1 - "1");
console.log(1 * "2");
console.log(1 * "one");

// 결과
0
2
NaN
  • 자바스크립트 엔진은 위의 산술 연산자(- 와 *) 표현식을 평가하기 위해 피연산자 중 숫자가 아닌 피연산자를 암묵적으로 타입을 변환한다.
  • 이 때, 피연산자를 숫자 타입으로 변환할 수 없는 경우는 산술 연산을 수행할 수 없으므로 평가 결과는 NaN이 된다.
var exp = '1' > 0;
console.log(exp);

// 결과
true
  • 비교 연산자도 산술 연산자와 마찬가지로 숫자가 아닌 피연산자를 암묵적으로 타입을 변환한다.

🤔 의문

  • 자바스크립트 엔진은 숫자가 아닌 피연산자를 어떻게 암묵적으로 숫자 타입으로 변환시킬까?

단항 연산자(+)를 이용한다.

var str = "1";
console.log(typeof str);
console.log(typeof +str);

// 결과
string
number

예를 더 살펴보면 다음과 같다.

var zero = "0";
console.log(+zero);

var one = "one";
console.log(+one);

console.log(+true);
console.log(+false);
console.log(+null);
console.log(+undefined);

// 결과
0
NaN
1
0
0
NaN

9-3. 명시적 타입 변환

  • 명시적 타입 변환은 개발자가 의도적으로 타입을 변경하는 방법이다.
  • 주로 표준 빌트인 생성자 함수(String, Number 등)를 사용하거나 빌트인 메서드를 사용한다. 둘 다 자바스크립트에서 기본적으로 제공한다.

9-3-1. 문자열 타입으로 변환

  • 문자열 타입으로 변환하는 명시적 타입 변환은 다음과 같은 방법이 있다.
    1. String 생성자 함수 사용
    2. toString 메서드 사용
var number = 1;
console.log(typeof number);

// 1. String 생성자 함수 사용
console.log(typeof String(number));

// 2. Object.prototype.toString 메서드를 이용
console.log(typeof number.toString());

// 결과
number
string
string

9-3-2. 숫자 타입으로 변환

  • 숫자 타입으로 변환하는 명시적 타입 변환은 다음과 같은 방법이 있다.

    1. Number 생성자 함수 사용
    2. parseInt, parseFloat 메서드 사용
var str = "1";
console.log(typeof str);

// 1. String 생성자 함수 사용
console.log(typeof Number(str));

// 2. Object.prototype.toString 메서드를 이용
console.log(typeof parseInt(str));

// 결과
string
number
number

9-4. 단축 평가

9-4-1. 논리 연산자를 사용한 단축 평가

console.log("첫 번째 평가식" && "두 번째 평가식");
  • "첫 번째 평가식"과 "두 번째 평가식"이 모두 참일 때, 출력되는 것은 무엇일까?
  • 답은 "두 번째 평가식" 이다.
  • 논리곱(&&) 연산자는 두 개의 피연산자가 모두 true 일 때, true를 반환한다.
  • 첫 번째 피연산자인 "첫 번째 평가식"은 true로 평가된다. 하지만, 이 시점까지는 위 표현식을 평가할 수 없다. 다시 말해, 두 번째 피연산자가 논리곱 연산자의 평가 결과를 결정한다.
  • 따라서, 논리곱 연산자는 논리 연산의 결과를 결정하는 두 번째 피연산자인 "두 번째 평가식"을 반환한다.

console.log("첫 번째 평가식" || "두 번째 평가식");
  • "첫 번째 평가식"과 "두 번째 평가식"이 모두 참일 때, 출력되는 것은 무엇일까?
  • 답은 "첫 번째 평가식"이다.
  • 논리합(||) 연산자는 두 개의 피연산자 중 하나라도 true이면, true를 반환한다.
  • 첫 번째 피연산자인 "첫 번째 평가식"은 true로 평가된다. 그리고 이 시점에 굳이 두 번째 피연산자까지 평가해 보지 않아도 위 표현식을 평가할 수 있다.
  • 따라서, 논리합 연산자는 논리 연산의 결과를 결정하는 첫 번째 피연산자인 "첫 번째 평가식"을 반환한다.

9-4-2. 단축 평가란?

  • 결국, 단축 평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다.
  • 단축 평가는 다음과 같은 상황에서 유용하게 쓰인다.

1. 객체를 담은 변수가 null 혹은 undefined 인지 확인하고 프로퍼티를 참조할 때

var obj = null;
var value = obj.value;
console.log(value);

// 결과
"Uncaught TypeError: Cannot read properties of null"
  • 객체를 담은 변수가 객체가 아니라 null, undefined인 경우 객체의 프로퍼티를 참고하면 타입 에러가 발생한다. 따라서, 프로그램이 강제로 종료된다.
var obj = null;
var value = obj && obj.value;
console.log(value);

// 결과
null
  • 단축 평가를 사용하면 에러를 발생시키지 않는다.

2. 변수의 기본 값을 설정할 때

  • 예를 들어, www.velog.io/post 라는 가상 url로 접속하면 포스트 글을 나열해준다고 가정해보자.
  • 하지만, 게시글이 너무 많아 글을 20개씩 나누어 페이지네이션 작업을 하려고 한다.
  • 21~40 번의 글을 띄우려고 한다면 www.velog.io/post&page=2 로 querystring 값을 넘겨 처리할 수 있다.
// url: www.velog.io/post&page=2
const page = parseInt(request.query.page) || 1;
console.log(page);

// 결과
2
  • 1~20 번의 글은 www.velog.io/post로 접속했을 때 단축 평가를 사용해 page 값을 1로 초기화 해주면 된다.
// url: www.velog.io/post
const page = parseInt(request.query.page) || 1;
console.log(page);

// 결과
1
  • url에서 querystring으로 들어오는 값이 없으므로 단축 평가로 인해 page 변수가 1로 초기화 된다.

9-4-3. 옵셔널 체이닝 연산자

  • ES11(ECMAScript 2020)에서 도입된 옵셔널 체이닝(Optional Chaining) 연산자가 등장했다.
var obj = null;
var value = obj?.value;
console.log(value);

// 결과
undefined
  • 옵셔널 체이닝은 ?. 로 표현하는데, 이는 좌항의 피연산자가 null이나 undefined인 경우 undefined를 반환한다. 그렇지 않다면 우항의 프로퍼티 참조를 한다.
  • 옵셔널 체이닝 연산자와 논리곱 연산자의 차이점을 보자. 다음 코드는 어떻게 동작할까?
var str = "";
var len1 = str && str.length;
console.log(`len1: ${len1}`);

var len2 = str?.length;
console.log(`len2: ${len2}`);
  • 논리 연산자 && 는 좌항 피연산자가 false로 평가되므로 좌항 피연산자가 그대로 반환된다.
// 결과
"len1: " 
  • 옵셔널 체이닝 연산자는 좌항 피연산자가 false 값이라도 null이나 undefined 가 아니므로 우항의 프로퍼티 참조를 반환한다.
// 결과
"len2: 0" 

9-4-4. null 병합 연산자

  • ES11(ECMAScript 2020)에서 도입된 null 병합 연산자 ??는 좌항의 피연산자가 null이나 undefined 이면 우항의 피연산자를 반환하고 아니면 좌항의 피연산자를 반환한다.

  • 위에서 논리합(||)을 사용했던 페이지네이션 예시로 든 코드를 null 병합 연산자로 바꾸어 보면 다음과 같다.

// url: www.velog.io/post&page=2
const page = req.query.page ?? 2;
console.log(page);

// 결과
2

✏️ 참고

  • 실제로 테스트 해보니 null 병합 연산자에서 피연산자에 parseInt를 붙이면 NaN을 반환하므로 주의해야 한다.
  • 이처럼, null 병합 연산자는 변수에 기본 값을 설정할 때 유용하다.
  • null 병합 연산자와 논리합 연산자의 차이점을 보자. 다음 코드는 어떻게 동작할까?
var str1 = "" || "default";
console.log(`str1: ${str1}`);

var str2 = "" ?? "default";
console.log(`str2: ${str2}`);
  • 논리 연산자 || 는 좌항 피연산자가 false로 평가되므로 단축 평가에 의해 우항 피연산자인 "default"를 반환한다.
// 결과
"str1: default" 
  • null 병합 연산자는 좌항 피연산자가 false로 평가될지라도 null이나 undefined가 아니므로 좌항의 피연산자를 반환한다.
// 결과
"str2: "
profile
개발자가 되고 싶은 개발자

0개의 댓글