JS is Weird

김내현·2024년 10월 23일

개인공부

목록 보기
1/51
post-thumbnail

1. true + false

ECMAScript 언어 사양에 따르면 두 개의 부울 값은 숫자형 값으로 강제 형변환됩니다.
Number(true); // -> 1
Number(false); // -> 0
1 + 0; // -> 1

2. [,,,].length

[,,,]는 빈 슬롯이 3개 있는 배열을 출력합니다. 마지막 쉼표는 끝에 붙는 쉼표 입니다 .
아직 이상하다고 생각하지 않으시다면, 이걸 한번 보세요:
[,] + [,]; // -> ""
[] + [] === [,] + [,]; // -> true
[,,,] + [,,,]; // -> ",,,,"
([,,,] + [,,,]).length === [,,,,].length; // -> true
배열에서의 덧셈 연산자를 설명하는 자료를 찾으려면 바로 아래에 있는 질문 3에 대한 설명을 살펴보세요.

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

매우 단순화된 답은 배열이 문자열로 변환된 다음 연결된다는 것입니다. 이것이 어떻게 일어나는지에 대한 Denys Dovhan의 설명을 참조하세요 . 이 동작에 대해 자세히 알아보려면 중간 수준의 설명은 이 StackOverflow 답변을 방문하거나 더 자세한 설명은 이 블로그 게시물을 방문하세요.
그런데 끝에 쉼표를 하나 더 붙여도 아무것도 바뀌지 않습니다.
[1, 2, 3,] + [4, 5, 6]; // -> "1,2,34,5,6"
하지만 배열을 쉼표로 구분된 문자열로 변환하여 결합하고 싶다면 다음과 같이 어리석은 코드를 작성할 수 있습니다.
[1, 2, 3] + [, 4, 5, 6]; // -> "1,2,3,4,5,6"
아니면, 훨씬 더 어리석은 것은 다음과 같습니다.
[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

이것은 부동 소수점 값을 비교하는 표준적인 딜레마입니다. 두 부동 소수점을 직접 비교하는 대신, 어느 정도의 허용 오차를 두고 부동 소수점을 비교해야 합니다. 이 StackOverflow 답변은 이 문제를 더 자세히 설명합니다.
0.2 + 0.1; // -> 0.30000000000000004;
0.2 + 0.1 > 0.3; // -> true

5. 10,2

쉼표 연산자는 단순히 마지막 피연산자의 값을 반환합니다.
10, 2; // -> 2
1, 2, 3, 4; // -> 4
42, "pineapple", true; // -> true

6. !!""

값 앞에 느낌표 두 개를 추가하면 해당 boolean 값의 기본형을 얻을 수 있습니다. 이에 대한 기술 용어는 이중 NOT 입니다. 변환은 값의 진실성 또는 거짓성에 따라 이루어집니다.
!!""; // -> false
!!0; // -> false
!!"Pineapple"; // -> true
!!42; // -> true
동일한 변환은 Boolean 함수를 사용하여 수행할 수 있습니다.
Boolean(""); // -> false

7. +!![]

배열은 진실이므로 이중 NOT 연산자는 true를 출력합니다. 그런 다음 더하기 문자는 true를 숫자 표현으로 변환합니다: 1.
!![]; // -> true
+true; // -> 1
이 표현은 명확하게 쓰면 더 명확해질 수도 있습니다.
Number(Boolean([])); // -> 1

8. parseInt(0.0000005)

parseInt(0.5); // -> 0
parseInt(0.05); // -> 0
parseInt(0.005); // -> 0
parseInt(0.0005); // -> 0
parseInt(0.00005); // -> 0
parseInt(0.000005); // -> 0
parseInt(0.0000005); // -> 5
parseInt 함수 는 첫 번째 인수를 문자열로 변환하고(아직 문자열이 아니라면) 숫자로 변환합니다. 0.0000005가 문자열로 변환되면 다음과 같이 됩니다 .
String(0.0000005); // -> "5e-7"
parseInt 함수 는 그 문자열에서 첫 번째 문자인 5를 가져와서 그 문자만 숫자로 파싱합니다. 이 동작을 설명한 Dmitri Pavlutin 에게 모든 공을 돌립니다. 더 자세한 설명(대신 사용할 수 있는 대체 함수 포함)은 그의 웹사이트를 확인하세요.

9. true == "true"

추상적 동등 비교 규칙에 따라 , 두 값은 비교 시 모두 숫자로 변환됩니다.
Number(true); // -> 1
Number("true"); // -> NaN
1 == NaN; // -> false

10. 010 - 03

010은 JavaScript에서 8진수로 처리됩니다. 따라서 값은 8진수입니다. MDN 웹 문서는 8진수에 대한 간략한 설명을 제공합니다 .
010; // -> 8
03; // -> 3
8 - 3; // -> 5
원하시면 8진수를 사용해도 됩니다.
01111111111111111; // -> 40210710958665
그런데 앞에 오는 0의 개수는 중요하지 않습니다.
010 === 0000000010; // -> true

11. "" - - ""

이 두 개의 빈 문자열은 모두 0으로 변환됩니다.
Number(""); // -> 0
0 - - 0; // -> 0
이렇게 쓰면 표현이 조금 더 명확해질 수도 있을 것 같습니다.
+"" - -"";
+0 - -0;
여러분을 혼란스럽게 하려고 빼기 기호와 빈 문자열 사이에 공백을 두었지만 빼기 기호 사이의 공백 자체도 중요하다는 점에 유의하세요.
-(공백)-""; // -> 0
--""; // -> SyntaxError

12. null + 0

Null은 숫자형 표현인 0으로 변환됩니다.
Number(null); // -> 0
0 + 0; // -> 0
이는 또한...
null === false; // -> false
... 이건 사실이에요:
+null === +false; // -> true

13. 0/0

0/0 방정식에 대한 의미 있는 숫자적 답이 없으므로 출력은 단순히 NaN 입니다 .
isNaN(0/0); // -> true

14. 1/0 > 10 ** 1000

JavaScript는 이 두 값을 모두 무한대로 취급하고, 무한대는 무한대와 같습니다. 무한대에 대해 자세히 알아보세요.
1/0; // -> Infinity
10 ** 1000; // -> Infinity
Infinity > Infinity; // -> false
지수 연산자 ** 는 기본적으로 Math.pow 함수 와 동일 합니다 .
10 ** 1000; // -> Infinity
Math.pow(10, 1000); // -> Infinity

15. true++

첫 번째이자 유일한 구문 오류
많은 질문에 SyntaxError를 옵션으로 두고 있음
일부 사용자가 어떤 구문이 너무 이상해서 허용될 수 없다고 생각하기를 바래서 실제로 SyntaxError를 발생시키는 표현식을 추가
그런데 일부 전역 변수와 함수는 구문 오류를 발생시키지 않는다.
true++; // -> SyntaxError
1++; // -> SyntaxError
"x"++; // -> SyntaxError
null++; // -> SyntaxError
undefined++; // -> NaN
$++; // -> NaN
console.log++; // -> NaN
NaN++; // -> NaN
물론, 완전히 명확하게 하기 위해 말씀드리자면, 이는 유효한 구문입니다.
let _true = true;
_true++;
_true; // -> 2

16. "" - 1

덧셈 연산자 (+)는 숫자와 문자열에 모두 사용되는 반면, 뺄셈 연산자 (-)는 문자열에 용도가 없으므로 JavaScript는 이를 숫자 간의 연산으로 해석합니다. 빈 문자열은 0으로 강제 변환됩니다.
Number(""); // -> 0
0 - 1; // -> -1;
문자열 내부에 공백(또는 그 이상)이 있는 경우에도 이는 여전히 사실입니다.
" " - 1; // -> -1;
그러나 덧셈 연산자를 사용하면 문자열 연결을 우선합니다.
"" + 1; // -> "1";

17. (null - 0) + "0"

null은 0으로 강제 변환됩니다.
Number(null); // -> 0
0 - 0; // -> 0
0 + "0"; // -> "00"
만약 질문에 뺄셈 연산자만 사용했다면 결과는 달랐을 것입니다.
(null - 0) - "0"; // -> 0

18. true + ("true" - 0)

JS가 너무 이상해서 문자열 리터럴 "true"를 부울 true의 숫자 표현으로 변환할 것이라고 생각할 수도 있습니다. 하지만 그렇게 이상하지는 않습니다. 실제로 일어나는 일은 문자열을 숫자로 변환하려고 시도하다가 실패하는 것입니다.
Number("true"); // -> NaN

19. !5 + !5

엄숙한 느낌표(논리적 NOT 연산자라고도 함)를 부울이 아닌 값 앞에 붙이면 부울 함수가 변환하는 것과 반대되는 부울 값으로 변환됩니다.
5는 true입니다:
Boolean(5); // -> true
!!5; // -> true
물론, 참의 반대는 거짓이며, 거짓은 0으로 강제 변환됩니다.
!5; // -> false
+false; // -> 0
0 + 0; // -> 0

20. [] + []

이 질문은 질문 3과 밀접하게 연관되어 있습니다. 다시 말하지만, 매우 단순화된 답변은 JavaScript가 배열을 문자열로 변환한다는 것입니다. 이 동작을 설명하는 리소스를 찾으려면 오른쪽의 3을 클릭하세요.
[].toString(); // -> ""
"" + ""; // -> ""
또한, 질문 2에 대한 설명에서 언급했듯이, 이 표현은 끝에 쉼표가 있어도 동일합니다.
[] + [] === [,] + [,]; // -> true
이처럼 배열은 다르지만 둘 다 빈 문자열로 변환됩니다.
[].length; // -> 0
[,].length; // -> 1
[].toString() === [,].toString(); // -> true
물론, 이것도 사실입니다.
Number([]) === Number([,]); // -> true

21. 1 + 2 + "3"

JavaScript는 이러한 작업을 왼쪽에서 오른쪽으로 실행합니다. 숫자 3을 문자열 3에 더하면 문자열 연결이 우선합니다.
1 + 2; // -> 3
3 + "3"; // -> "33"
연산은 왼쪽에서 오른쪽으로 실행되므로 문자열을 포함한 연산이 첫 번째 연산인지 두 번째 연산인지에 따라 출력 결과가 크게 달라집니다.
"1" + 2 + 3; // -> "123"
1 + "2" + 3; // -> "123"

22. typeof NaN

ECMAScript 언어 사양에서는 NaN을 IEEE 754 "Not-a-Number" 값인 숫자 값으로 설명합니다. 이상하게 보일 수 있지만, 이는 일반적인 컴퓨터 과학 원리입니다.
그러나 JavaScript에서 NaN을 둘러싼 몇 가지 이상한 문제가 있습니다. 예를 들어, 이것은 Object.is 함수가 트리플 등호와 일치하지 않는 두 가지 유일한 사례 중 하나입니다.
NaN === NaN; // -> false
Object.is(NaN, NaN); // -> true
값이 NaN인지 확인하려면 항상 isNaN 함수를 사용해야 합니다.
isNaN(NaN); // -> true
관련 없지만 Object.is 함수가 삼중 등호와 일치하지 않는 다른 경우가 궁금하다면 , 그것은 0과 -0입니다.
0 === -0; // -> true
Object.is(0, -0); // -> false

23. undefined + false

false는 숫자로 변환될 수 있지만 undefined는 숫자로 변환될 수 없습니다.
Number(undefined); // -> NaN
Number(false); // -> 0
NaN + 0; // -> NaN
그러나 undefined는 false로 표현 됩니다 .
!!undefined === false; // -> true
즉, 다음과 같이 undefined와 false를 추가할 수 있습니다.
!!undefined + false; // -> 0

24. "" && -0

여러분은 if 문에서만 논리적 AND 연산자를 사용했을 가능성이 있지만 , 단독으로 사용되면 실제로 피연산자 중 하나의 값을 반환합니다. 첫 번째 표현식이 참이면 두 번째 표현식을 반환합니다. 그렇지 않으면 첫 번째 표현식을 반환합니다. 빈 문자열은 거짓이므로 첫 번째 피연산자를 반환합니다.
"" && -0; // -> ""
-0 && ""; // -> -0
5 && 3; // -> 3
0 && 3; // -> 0

25. +!!NaN * "" - - [,]

피날레는 이 퀴즈에서 다룬 기괴한 구문 중 일부를 결합합니다. 위의 설명에서 이미 모든 동작을 설명했지만, 곱셈 연산자(*)는 비어 있는 문자열을 숫자로 변환합니다: 0.
+!!NaN; // -> 0
+""; // -> 0
-[,]; // -> -0
모두 합치면 다음과 같습니다.
0 * 0 - -0; // -> 0

0개의 댓글