JS
는 자유도(?)가 워낙 높아 이상하다는 것을 알고 있었지만, 막상 JS is Weird를 풀어 보니 절반도 못 맞췄다. 그 충격을 정리한다.
문제와 답을 함께 적을 예정이라 스포일러가 될 수 있다. 스크롤을 내리기 전에 풀어보는 편이 좋다.
answer : 1
다행히 처음 문제는 쉬웠다. true
는 1로, false
는 0으로 치환된다. 그러므로 답은 1
이다.
answer : 3
배열의 콤마(,
)는 빈 요소를 구분한다. 눈으로 보기에는 4칸이지만 길이가 3인 이유는 마지막 콤마가 후행 쉼표(Trailing commas)이기 때문이다. 새 요소나 매개변수, 속성 등을 추가하기 쉽도록 고안된 JS
고유 문법이라고 한다.
이걸 가지고 연산하는 사람은 없겠지만, 연산하는 순간 이상해진다.
[ , , , ] + [ , , ] // ",,,"
([,,,] + [,,,]).length // 4
[,,,,].length // 4
배열과 배열을 더하면 배열 요소와 콤마가 합쳐진 문자열이 되는데, 후행 쉼표는 생략된다. 음, 보기 싫은 광경이다.
answer : "1,2,34,5,6"
위에서 설명한 바와 같다. 3
과 4
이 합쳐지는 게 보기 불편하다면 다음과 같은 방법이 있다고 알려준다.
[1, 2, 3] + [, 4, 5, 6];
[1, 2, 3, ""] + [4, 5, 6];
가장 좋은 방법은 +
연산자를 사용하지 않고 배열을 합치는 것이라고. (진짜 배열을 더하는 사람이 있긴 할까? 의아, 궁금)
[...[1, 2, 3], ...[4, 5, 6]];
answer : false
워낙 유명한 문제라 맞췄다. JS
의 부동소수점과 관련 있는데 stackoverflow에 자세한 답변이 있다.
answer : 2
이 글을 쓰게 된 계기인데, ,
가 어떻게 연산자인 거냐고! Comma operator라니... 정말 충격과 공포 그 자체였다. 이제라도 알아서 다행이다.
answer : false
빈 문자열은 falsy
이고, boolean을 역전시키는 Logical NOT을 사용하면 true
가 된다. 한 번 더 NOT
을 하면 다시 역전되어 false
가 된다.
answer : 1
빈 배열은 놀랍게도 truthy
이다. 따라서 !!
의 값은 true
이고, +
하면 숫자가 되므로 1
이 나온다.
answer : 5
어, 음... 정수로 만들어주는 함수 아니었나? 설명을 보면 소수점 아래 7번째부터 달라지는 듯하다. String(0.0000005)
의 값은 5e-7
인데, parseInt
는 e-7
을 스킵한다. Solving a Mystery Behavior of parseInt() in JavaScript
세상에 마상에...
answer : false
1 == "1"
은 true
라며? 그래서 틀렸다. 1
, "1"
, true
는 number로 변환되지만, "true"
는 NaN
이 되기 때문이다. 1 == NaN
은 false
다.
answer : 5
0
은 자동 생략되어서 10 - 3
인줄 알았는데 아니었다. 무려 010
은 8진수였다! 앞에 0
이 붙고 뒤가 7이하의 수라면 JS
은 8진수로 세팅한다. 8이상은 10진수로. 이게 똑똑한 건지, 멍청한 건지 모르겠다. 으아아아아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ
answer : 0
이게 왜 연산이 되는 건데?! "" - - ""
를 보기 쉽게 표현하면 다음과 같다.
+"" - -"";
+0 - -0;
근데 이건 에러다.
--""; // -> SyntaxError
answer : 0
null
의 타입이 object여서 NaN
이 나올 줄 알았다. 지금 보니 +
연산을 숫자와 할 때는 number로 치환이 가능하냐에 따라 달라지는 듯하다, 라고 하기엔 "" + 1
은 "1"
인데. true = 1
, false = 0
, null = 0
이라고 외우자.
answer : NaN
하도 이상하게 당해서 이것도 이상하게 나오겠지 싶어 Infinity
를 선택했지만 아니었다. 정신 나갈 것 같다. ㅋㅋㅋㅋㅋ
answer : false
10 ** 1000
은 유한한 정수여서 Infinity
가 더 크다고 생각했다. 하지만 10의 1000승은 마찬가지로 Infinity
였다.
answer : SyntaxError
이것까지 증가되지는 않았다. 그래도 양심은 있네.
answer : -1
"" + 1"
은 문자열이면서 -
연산자는 숫자다.
answer : "00"
NaN
일 줄 알았는데, (null -0)
은 0
이고 문자열과 더해 "00"
이 되었다. 이제 좀 보인다.
answer : NaN
("true" - 0)
이 NaN
이어서 정답을 맞췄다.
answer : 0
false + false
라고 생각하면 되니까 답은 0
. 만약 !0 + !0
이었다면 답은 2
다.
answer : ""
제일 앞에서 했던 것의 반복이었다.
answer : "33"
number + string
or string + number
는 string
을 반환한다. 앞의 숫자 연산 후 문자열을 더해 "33"
이 되었다.
answer : number
처음 JS
를 배울 때 stirng
, object
혹은 NaN
이라는 타입이라고 생각했지만, 이것은 숫자가 아님을 나타내는 number
타입(Not a Number)이었다. '잉?'했던 느낌을 잊을 수가 없다.
answer : NaN
undefined
는 undefined
타입이다. 연산이 안 되므로 NaN
이 나온다.
answer : ""
빈 문자열은 falsy
니까 false
아닌가? 네, 아닙니다. Logical AND 연산자는 if
문이 아닌 경우 반환값이 Boolean이 아니다. 첫 번째 표현식이 true
이면 두 번째 표현식을 반환하고, 아니라면 첫 번째 표현식을 반환한다.
React에서 0 && <Component />
로 조건부 렌더링했을 때 0
이 나오는 경우가 이것 때문인가 보다. 0
이 falsy
이므로 첫 번재 표현식이 반환되는 것.
answer : 0
정신 나가서 포기했다. 지금 보니 0
인 게 보인다. +!!NaN
은 0
이다. "" - - [,]
는 "" - - ""
이고, 이건 위에서 0
임을 알았다. 그러므로 0 * 0 = 0
이 된다.
정신이 한 번 나갔지만, 정리하면서 정신줄 붙잡고 '나는 이런 코드 생각도 말아야지'라는 다짐을 하게 되었다. 호기심 해결되는 문제도 있어 도움이 되었다. JS
는 많이 이상한 언어지만, 내가 배우고 사용하는 만큼 더 열심히 공부해야겠다. 언젠가 개발자가 되는 그날을 위하여!