
* 모던 자바스크립트 Deep Dive을 토대로 공부한 것을 정리한 내용으로, 모든 인용문은 모던 자바스크립트 Deep Dive의 문구를 인용한 것입니다.
개발자의 의도에 따라 다른 타입으로 변환하는 것을 명시적 타입 변환 혹은 타입 캐스팅이라고 한다.
개발자의 의도와는 상관없이 표현식을 평가하는 도중에 자바스크립트 엔진에 의해 암묵적으로 타입이 변환되는 것을 암묵적 타입 변환 혹은 타입 강제 변환이라고 한다.
암묵적 타입 강제 변환은 자바스크립트 엔진에 의해 드러나지 않게 자동 변환되기 때문에 타입을 변경하겠다는 개발자의 의지가 코드에 명백히 나타나지 않는다.
즉, 코드에서 암묵적 타입 변환이 발생하는지, 발생한다면 어떤 값으로 변환되며 어떻게 평가될 것인지 예측 가능해야 한다.
-> 그렇다면 명시적 타입 변환만 사용하면 되는 것이 아닌가?
때로는 명시적 타입 변환이 암묵적 타입 변환보다 가독성 측면에서 좋을 수 있기 때문에 옳지 않은 논리이다.
// 피연산자가 모두 문자열 타입이어야 하는 문맥
'10' + 2 // '102'
// 피연산자가 모두 숫자 타입어야 하는 문맥
5 * '10' // 50
// 피연산자 또는 표현식이 타입이어야 하ㅡㄴ 문맥
!0 //true
if (1) {}
위의 예제처럼 표현식을 평가할 때 코드의 문맥에 부합하지 않는 다양한 상황이 발생할 수 있다. 이때 오류를 발생시키기도 하지만, 자바스크립트는 가급적 에러를 발생시키지 않도록 하기 위해 암묵적 타입 변환을 통해 표현식을 평가한다.
이때, 암묵적 타입 변환으로 인해 개발자가 타입 변환 자체 혹은 결과를 인지하지 못하고 있을 때 오류 발생 확률이 높아진다.
// 숫자 타입에서 문자 타입으로 변환
0 + '' // '0'
1 + '' // '1'
-1 + '' //'-1'
NaN + '' // 'NaN'
Infinity + '' // 'Infinity'
// 불리언 타입에서 문자 타입으로 변환
true + '' // 'true'
false + '' // 'false'
// null 타입에서 문자 타입으로 변환
null + '' // 'null'
// undifined 타입에서 문자 타입으로 변환
undifined + '' // 'null'
// 객체 타입에서 문자 타입으로 변환
({}) + '' // '[object Object]'
Math + '' // '[object Math]'
[] + '' // ''
[1,2] + '' // '1,2'
(function(){}) + '' // 'function(){}'
Array + '' // 'function Array(){ [native code] }'
// 문자열 타입을 숫자 타입으로 변환
+'' // 0
+'0' // 0
+'String' // NaN
// 불리언 타입을 숫자 타입으로 변환
+true // 1
+false // 0
// null 타입을 숫자 타입으로 변환
+null // 0
// undifined 타입을 숫자 타입으로 변환
+undifined // NaN
// 심벌 타입을 숫자 타입으로 변환
+Symbol() // TypeError: 심벌 타입은 숫자로 변환할 수 없다
// 객체 타입
+{} // NaN
+[] // 0
+[10, 20] // NaN
+(function(){}) // NaN
자바스크립트 엔진은 불리언 타입이 아닌 값을 Truthy 혹은 Falsy 값으로 구분한다.
false으로 평가되는 Falsy 값들은 아래와 같다.
- false
- undifined
- null
- 0, -0
- NaN
- ''(빈 문자열)
문자열 타입이 아닌 값을 문자열 타입으로 변환하는 법
- String 생성자 함수를 new 연산자 없이 호출하는 방법
- Object.prototype.toString 메서드를 사용하는 방법
- 문자열 연결 연산자를 이용하는 방법
숫자 타입이 아닌 값을 숫자 타입으로 변환하는 법
- Number 생성자 함수를 new 연산자 없이 호출하는 방법
- parseInt, parseFloat 함수를 사용하는 방법(문자열=>숫자만 가능)
+당항 산술 연산자를 이용하는 방법*산술 연산자를 이용하는 방법
불리언 타입이 아닌 값을 불리언 타입으로 변환하는 방법
- Boolean 생성자 함수를 new 연산자 없이 호출하는 방법
- ! 부정 논리 연산자를 두 번 사용하는 방법
논리곱(&&) 연산자는 두 개의 피연산자가 모두 true일 때 true를 반환한다. 논리곱 연산자는 좌항에서 우항으로 평가가 진행된다.
논리합(||) 연산자는 두 개의 피연산자 중 하나만 true여도 true를 반환한다. 논리합 연산자도 좌항에서 우항으로 평가가 진행된다.
| 단축 평가 표현식 | 평가 결과 |
|---|---|
| true (논리합) anything | true |
| false (논리합) anything | false |
| true && anything | anything |
| false && anything | false |
위에 표를 직접 그리긴 했지만 논리합 기호를 표현하지 못하기도 하고 더 자세한 표가 있는 것 같아서 가져왔다.
옵셔널 체이닝 연산자(?.)는 좌항의 피연산자가 null 혹은 undifined일 경우 undifined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
var elem = null;
var value = elem?.value;
console.log(value); // undifined
위의 예제에서는 좌항의 elem이 null이기 때문에 undifined를 반환한다.
null 병합 연산자(??)는 좌항의 피연산자가 null 또는 undifined일 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.
var foo = null ?? 'default string';
console.log(foo); // default string
위의 예제에서는 좌항의 피연산자가 null이기 때문에 우항의 default string를 반환했다.
null 병합 연산자는 변수에 기본값을 설정할 때 유용하다.
자바스크립트의 이론적인 부분을 공부해본 적이 없어서 사용했던 옵셔널 체이닝 연산지나 null 병합 연산자의 이론적인 부분이 굉장히 반가웠다. 앞으로는 사용하고 이론을 알기보단 이론을 먼저 배우는 게 좋을 것 같다!
또한 평소 암묵적 타입 변환을 잘 활용하지 못하였는데, 책에 예제가 많이 나와 있어 암묵적 타입 변환에 대해서 많이 고민해보았다. 암묵적 타입 변환과 같이 간단한 이론이 오히려 활용할 때 생각이 더 안 나는 것 같다... 🥲🥺 오랜만에 알고리즘 공부하는 기분이 들었다!
그리고 타입 변환할 때... 그럼 메모리는 어떻게 되는 거지? 라는 생각이 들어 계속 찾아봤는데 너무 컴퓨터구조적인 내용이라 잘 모르겠다... 만약 불리언에서 숫자 타입으로 변경하면 1byte 할당된 공간에 4byte의 숫자가 못 들어오는 거 아닌가?... 라는 생각을 했다... 동적 타입은 메모리 할당이 변경될 수 있는 건가?? 애초에 4byte로 모두 할당하는 건가? 싶긴 했지만 그러면 메모리 차원에서 너무 손해같아서 그렇게는 아닐 것 같다는 생각도 들었다.... 스터디 때까지 고민해 봐야겠다
+추가 ) 바보같은 고민이었다... 이미 할당된 곳에 변경하는 것이 아니라 새로운 메모리에 값을 할당하고 변수는 새로운 메모리 주소를 기억하는 것이다....... 너무 어렵게 생각해서 그랬나 왜 놓쳤지?? 근데 그러면 메모리 누수가 너무 심하지 않나??
++) 진짜진짜 바보였다... 생각해보니까 메모리 누수를 방지하기 위해서 자바스크립트 엔진에는 가비지 컬렉션이 있다...
내가 모르는 부분을 자세히 읽고 넘어가는 게 중요한 것 같다!! 항상 실습에 몸통 박치기만 했어서 이렇게 이론적인 부분을 따로 공부하는 게 오랜만이라 열심히 해야겠다는 생각이 들었다...
저랑 공부 방식이 비슷하셨네요 ㅋㅋㅋ
저도 실습으로 머리통깨지면서 일단 습득한 후에 이론을 학습하는 스타일이라^*^
근데 이런 방식도 나쁘진 않은 것 같아요! 알게모르게 실습으로 습득한 지식에 대해서 궁금해지는 날이 오더라구요.
어쨌든 당장 개발에 필요한 부분을 알기에는 이론적 내용을 앞서 공부하기 보다는 저희처럼 실습으로 머리깨지면서 배워도 괜찮은 것 같습니다 ㅎㅎ :)