모던자바스크립트 스터디 14일차이다.
29장 Math
30장 Date
오늘은 위 단원들을 공부하고 모르는것을 정리했다.
# 궁금증 1
왜 Math.abs([])는 0이고 Math.abs({})는 NaN을 반환하는가?
# 이유
Math.abs([]) (빈 배열)
console.log(Math.abs([])); // 0
빈 배열을 Math.abs() 함수에 전달할 때 JavaScript는 배열을 암시적으로 숫자로 변환한다.
빈 배열에 대한 이 변환은 0으로 이루어지며, 따라서 Math.abs(0)은 단순히 0이 된다.
이 동작은 JavaScript가 값들을 숫자로 강제 변환하는 방식에 기인한다.
Math.abs({}) (빈 객체)
console.log(Math.abs({})); // NaN
빈 객체를 Math.abs() 함수에 전달하면 JavaScript는 객체를 숫자로 변환하려고 시도한다.
그러나 빈 객체는 직접적으로 숫자로 변환될 수 없기 때문에 결과는 NaN(숫자가 아님)이다.
빈 객체의 경우 객체를 기본 값(primitive value)으로 변환하는 과정에서 객체의 valueOf 및 toString 메서드가 호출되는데, 빈 객체의 경우 이러한 메서드가 유효한 숫자 표현을 반환하지 않기 때문에 NaN을 반환한다.
- valueOf
- 객체의 valueOf 메서드는 객체를 원시 값으로 변환하려고 할 때 호출된다.
- valueOf 메서드를 정의하면 JavaScript는 해당 메서드의 반환 값을 사용하여 객체를 원시 값으로 변환한다.
- 만약 valueOf 메서드가 객체를 반환하지 않거나 반환 값이 원시 값이 아니면, JavaScript는 다음으로 toString 메서드를 호출한다.
- toString
- 객체의 toString 메서드는 valueOf 메서드가 원시 값으로의 변환을 처리하지 못할 때 호출된다.
- toString 메서드를 정의하면 JavaScript는 해당 메서드의 반환 값을 사용하여 객체를 원시 값으로 변환한다.
- toString 메서드가 원시 값을 반환하지 않으면, JavaScript는 오류가 아닌 [object Object]와 같은 기본 문자열 표현을 반환한다.
# 결론
Math.abs({}) 이 NaN인 이유
Math.abs 함수는 내부적으로 valueOf 메서드를 호출하여 객체를 원시 값으로 변환하려고 한다.
그러나 대부분의 객체에서는 valueOf 메서드가 명시적으로 구현되어 있지 않기 때문에 valueOf가 객체 자체를 반환한다.
valueOf가 객체 자체를 반환하는 경우, JavaScript는 toString 메서드를 호출하여 객체를 문자열로 변환한다.
대부분의 객체는 기본적으로 Object.prototype.toString 메서드를 상속받는다.
Object.prototype.toString 메서드는 "[object Object]"와 같은 문자열을 반환한다.
"[object Object]"은 원시 값이 아니기 때문에 Math.abs 함수는 최종적으로 NaN을 반환하게 된다.
Math.abs([]) 이 0인 이유
대부분의 배열은 valueOf 메서드가 명시적으로 구현되어 있지 않기 때문에 valueOf가 배열 자체를 반환하게 된다.
이후, JavaScript는 toString 메서드를 호출하여 배열을 문자열로 변환한다.
대부분의 배열은 Array.prototype.toString 메서드를 상속받으며, 이 메서드는 배열의 요소를 쉼표로 구분한 문자열을 반환한다.
빈 배열인 경우에는 빈 문자열이 반환된다.
최종적으로, 빈 문자열이 숫자로 변환되면 빈 문자열은 0으로 해석되므로 Math.abs([])는 0을 반환하게 된다.
# 궁금증 2
왜 Date 모듈을 사용하는 것을 추천하지 않을까?
대안으로 Day.js를 추천하는 이유는 뭘까?
# 이유
1. 날짜만을 지원하지 않음
Javascript는 날짜와 시간(Datetime)만을 지원한다.
즉, 날짜를 만들려고 하면 실제로는 날짜 시간을 만든다.
시간이 지정되지 않은 모든 Javascript 날짜는 기본적으로 해당 날짜의 자정으로 설정된다.
2. Date Parsing 문제
원칙대로면 위처럼 ISO-8601 표준을 준수하는 문자열만 Javascript로 Parsing 할 수 있어야한다.
근데, 크롬을 비롯한 많은 브라우저에서 mm/dd/yyyy 형식을 지원하므로 혼동이 생길 수 있다.
참고로, 최신 브라우저는 미국 날짜 형식인(mm/dd/yyyy)를 사용해서 11월 3일 2023년이 아니라, 3월 11일 2023년이 된다.
3. 기본값이 UTC
utc 시간대가 기본이라서 한국은 9시간이 더 빠르다.
그래서 1월 1일부터 1월 31일까지 해당월을 조회한다고 했을때, utc가 기본이라 12월31일부터 1월 30일까지 조회될 수가 있다는 문제가 발생한다.
4. 월이 0부터 시작함
내 의도는 2023년 1월 22일이었다.
근데, 2023년 2월 22일이 반환되었다.
0이 1월이라서 1이 2월이 되어 1씩 당겨진것이다.
이런것을 계산해야하는 단점이 있다.
5. 이상한 반환값
내 의도는 2023년 1월 31일이었다.
근데 2023년 3월 3일이 반환되었다.
1. 0부터 시작하니까 1 -> 2월이 반환된다.
2. 2023년에는 2월이 28일밖에 없고 3일이 추가되었으므로 남은 날짜가 다음달로 넘어간다.
3. 3월에 남은 날짜 3일이 추가되서 2023년 3월 3일이 리턴된다.
6. 문자열이 숫자로 Parsing 되지 않음
내 의도는 0년 또는 unix time을 기대했지만, 2000년도를 반환한다.
그럼 숫자로 0을 넣으면 어떻게 되는지 넣어봤더니
시작값인 1970년 1월 1일을 리턴했다.
마찬가지로 숫자 1개만 넣어도 1970을 리턴한다.
하지만 월이 0~11까지라 이걸 넘는 문자열인 13을 넣으니 Invalid Date라고 에러가 떴다.
7. 연월일이 이상하게 리턴됨
위에서는 "0" 하나만 넣으면 1970년도로 뜨더니
이제 0, 0, 0 인 연월일을 맞춰서 넣으니 1899년 12월 31일이 뜬다.
이렇게 기준을 잘 모르겠다보니까 사용하기가 어려운것 같다.
# Day.js를 추천하는 이유는?
1. Moment.js의 문제점
우선 moment.js는 지원을 중단했다.
use case의 범위를 초과하는 광범위한 Date 연산을 지원하기 때문이다.
이는 번들에 포함된 Moment.js 코드 중 사용되지 않는 부분이 더 크다는 것을 의미한다.
사용하지도 않는 기능들 때문에 빌드시 용량이 커지게 되어서 빌드 속도가 느려지고, 이는 서버의 전체 용량을 불필요하게 사용하게 된다.
그래서 사용하는 것만 빌드해서 경량화를 시키는 것이 비용관리 측면에서 유리하다.
2. Day.js의 장점
- 기본적인 기능만 포함하여 매우 작은 사이즈이다(2KB)
- Moment.js와 똑같은 인터페이스라서 넘어가기 쉽다.(대부분의 moment.js use case 적용 가능)
- immutable을 지원해서 날짜가 생성된 후에도 날짜를 변경할 수 있다는 위험성을 방지한다.
- internationalization(국제화) 지원
나는 moment.js를 사용중이었기 때문에 day.js로 쉽게 넘어갈 수 있었다.
그래서 day.js를 추천받았던 것이다.
# 참고
valueOf 및 toString 메서드
https://dev.to/composite/valueof-mesodeu-mweohareo-issnya-1n97
Date 모듈 문제점
https://fjolt.com/article/javascript-date-is-weird
Day.js
'JaveScript > JaveScript' 카테고리의 다른 글
모던자바스크립트 37, 38장 스터디 (0) | 2023.12.04 |
---|---|
모던자바스크립트 33, 34장 스터디 (0) | 2023.12.02 |
V8에서 자바스크립트 변수는 어떻게 관리될까? (4) | 2023.11.29 |
자바스크립트의 배열은 리스트 동적할당을 어떻게 할까? (0) | 2023.11.28 |
모던자바스크립트 27, 28장 스터디 (1) | 2023.11.27 |