[JS] JavaScript는 이상하다

찐새·2023년 11월 22일
1

Javascript

목록 보기
11/11
post-thumbnail

JS는 자유도(?)가 워낙 높아 이상하다는 것을 알고 있었지만, 막상 JS is Weird를 풀어 보니 절반도 못 맞췄다. 그 충격을 정리한다.

스포일러 주의

문제와 답을 함께 적을 예정이라 스포일러가 될 수 있다. 스크롤을 내리기 전에 풀어보는 편이 좋다.

1. true + false (O)

answer : 1

다행히 처음 문제는 쉬웠다. true는 1로, false는 0으로 치환된다. 그러므로 답은 1이다.

2. [ , , , ].length (O)

answer : 3

배열의 콤마(,)는 빈 요소를 구분한다. 눈으로 보기에는 4칸이지만 길이가 3인 이유는 마지막 콤마가 후행 쉼표(Trailing commas)이기 때문이다. 새 요소나 매개변수, 속성 등을 추가하기 쉽도록 고안된 JS 고유 문법이라고 한다.

이걸 가지고 연산하는 사람은 없겠지만, 연산하는 순간 이상해진다.

[ , , , ] + [ , , ] // ",,,"
([,,,] + [,,,]).length // 4
[,,,,].length // 4

배열과 배열을 더하면 배열 요소와 콤마가 합쳐진 문자열이 되는데, 후행 쉼표는 생략된다. 음, 보기 싫은 광경이다.

3. [1, 2, 3] + 4, 5, 6

answer : "1,2,34,5,6"

위에서 설명한 바와 같다. 34이 합쳐지는 게 보기 불편하다면 다음과 같은 방법이 있다고 알려준다.

[1, 2, 3] + [, 4, 5, 6];
[1, 2, 3, ""] + [4, 5, 6];

가장 좋은 방법은 + 연산자를 사용하지 않고 배열을 합치는 것이라고. (진짜 배열을 더하는 사람이 있긴 할까? 의아, 궁금)

[...[1, 2, 3], ...[4, 5, 6]];

4. 0.2 + 0.1 === 0.3 (O)

answer : false

워낙 유명한 문제라 맞췄다. JS의 부동소수점과 관련 있는데 stackoverflow에 자세한 답변이 있다.

5. 10,2 (X)

answer : 2

이 글을 쓰게 된 계기인데, ,가 어떻게 연산자인 거냐고! Comma operator라니... 정말 충격과 공포 그 자체였다. 이제라도 알아서 다행이다.

6. !!"" (O)

answer : false

빈 문자열은 falsy이고, boolean을 역전시키는 Logical NOT을 사용하면 true가 된다. 한 번 더 NOT을 하면 다시 역전되어 false가 된다.

7. +!

answer : 1

빈 배열은 놀랍게도 truthy이다. 따라서 !!의 값은 true이고, +하면 숫자가 되므로 1이 나온다.

8. parseInt(0.0000005)

answer : 5

어, 음... 정수로 만들어주는 함수 아니었나? 설명을 보면 소수점 아래 7번째부터 달라지는 듯하다. String(0.0000005) 의 값은 5e-7인데, parseInte-7을 스킵한다. Solving a Mystery Behavior of parseInt() in JavaScript

세상에 마상에...

9. true == "true" (X)

answer : false

1 == "1"true라며? 그래서 틀렸다. 1, "1", true는 number로 변환되지만, "true"NaN이 되기 때문이다. 1 == NaNfalse다.

10. 010 - 03 (X)

answer : 5

0은 자동 생략되어서 10 - 3인줄 알았는데 아니었다. 무려 0108진수였다! 앞에 0이 붙고 뒤가 7이하의 수라면 JS은 8진수로 세팅한다. 8이상은 10진수로. 이게 똑똑한 건지, 멍청한 건지 모르겠다. 으아아아아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ

11. "" - - "" (X)

answer : 0

이게 왜 연산이 되는 건데?! "" - - ""를 보기 쉽게 표현하면 다음과 같다.

+"" - -"";
+0 - -0;

근데 이건 에러다.

--""; // -> SyntaxError

12. null + 0 (X)

answer : 0

null의 타입이 object여서 NaN이 나올 줄 알았다. 지금 보니 + 연산을 숫자와 할 때는 number로 치환이 가능하냐에 따라 달라지는 듯하다, 라고 하기엔 "" + 1"1"인데. true = 1, false = 0, null = 0이라고 외우자.

13. 0/0 (X)

answer : NaN

하도 이상하게 당해서 이것도 이상하게 나오겠지 싶어 Infinity를 선택했지만 아니었다. 정신 나갈 것 같다. ㅋㅋㅋㅋㅋ

14. 1/0 > 10 ** 1000 (X)

answer : false

10 ** 1000은 유한한 정수여서 Infinity가 더 크다고 생각했다. 하지만 10의 1000승은 마찬가지로 Infinity였다.

15. true++ (X)

answer : SyntaxError

이것까지 증가되지는 않았다. 그래도 양심은 있네.

16. "" - 1 (X)

answer : -1

"" + 1"은 문자열이면서 - 연산자는 숫자다.

17. (null - 0) + "0" (X)

answer : "00"

NaN일 줄 알았는데, (null -0)0이고 문자열과 더해 "00"이 되었다. 이제 좀 보인다.

18. true + ("true" - 0) (O)

answer : NaN

("true" - 0)NaN이어서 정답을 맞췄다.

19. !5 + !5 (O)

answer : 0

false + false라고 생각하면 되니까 답은 0. 만약 !0 + !0이었다면 답은 2다.

20. [] +

answer : ""

제일 앞에서 했던 것의 반복이었다.

21. 1 + 2 + "3" (O)

answer : "33"

number + string or string + numberstring을 반환한다. 앞의 숫자 연산 후 문자열을 더해 "33"이 되었다.

22. typeof NaN (O)

answer : number

처음 JS를 배울 때 stirng, object 혹은 NaN이라는 타입이라고 생각했지만, 이것은 숫자가 아님을 나타내는 number 타입(Not a Number)이었다. '잉?'했던 느낌을 잊을 수가 없다.

23. undefined + false (O)

answer : NaN

undefinedundefined 타입이다. 연산이 안 되므로 NaN이 나온다.

24. "" && -0 (X)

answer : ""

빈 문자열은 falsy니까 false 아닌가? 네, 아닙니다. Logical AND 연산자는 if문이 아닌 경우 반환값이 Boolean이 아니다. 첫 번째 표현식이 true이면 두 번째 표현식을 반환하고, 아니라면 첫 번째 표현식을 반환한다.

React에서 0 && <Component />로 조건부 렌더링했을 때 0이 나오는 경우가 이것 때문인가 보다. 0falsy이므로 첫 번재 표현식이 반환되는 것.

25. +!!NaN * "" - - [,] (Give up)

answer : 0

정신 나가서 포기했다. 지금 보니 0인 게 보인다. +!!NaN0이다. "" - - [,]"" - - ""이고, 이건 위에서 0임을 알았다. 그러므로 0 * 0 = 0이 된다.

결론

정신이 한 번 나갔지만, 정리하면서 정신줄 붙잡고 '나는 이런 코드 생각도 말아야지'라는 다짐을 하게 되었다. 호기심 해결되는 문제도 있어 도움이 되었다. JS는 많이 이상한 언어지만, 내가 배우고 사용하는 만큼 더 열심히 공부해야겠다. 언젠가 개발자가 되는 그날을 위하여!

profile
프론트엔드 개발자가 되고 싶다

0개의 댓글