ECMAScript 언어 사양에 따르면 두 개의 부울 값은 숫자형 값으로 강제 형변환됩니다.
Number(true); // -> 1
Number(false); // -> 0
1 + 0; // -> 1
[,,,]는 빈 슬롯이 3개 있는 배열을 출력합니다. 마지막 쉼표는 끝에 붙는 쉼표 입니다 .
아직 이상하다고 생각하지 않으시다면, 이걸 한번 보세요:
[,] + [,]; // -> ""
[] + [] === [,] + [,]; // -> true
[,,,] + [,,,]; // -> ",,,,"
([,,,] + [,,,]).length === [,,,,].length; // -> true
배열에서의 덧셈 연산자를 설명하는 자료를 찾으려면 바로 아래에 있는 질문 3에 대한 설명을 살펴보세요.
매우 단순화된 답은 배열이 문자열로 변환된 다음 연결된다는 것입니다. 이것이 어떻게 일어나는지에 대한 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]];
이것은 부동 소수점 값을 비교하는 표준적인 딜레마입니다. 두 부동 소수점을 직접 비교하는 대신, 어느 정도의 허용 오차를 두고 부동 소수점을 비교해야 합니다. 이 StackOverflow 답변은 이 문제를 더 자세히 설명합니다.
0.2 + 0.1; // -> 0.30000000000000004;
0.2 + 0.1 > 0.3; // -> true
쉼표 연산자는 단순히 마지막 피연산자의 값을 반환합니다.
10, 2; // -> 2
1, 2, 3, 4; // -> 4
42, "pineapple", true; // -> true
값 앞에 느낌표 두 개를 추가하면 해당 boolean 값의 기본형을 얻을 수 있습니다. 이에 대한 기술 용어는 이중 NOT 입니다. 변환은 값의 진실성 또는 거짓성에 따라 이루어집니다.
!!""; // -> false
!!0; // -> false
!!"Pineapple"; // -> true
!!42; // -> true
동일한 변환은 Boolean 함수를 사용하여 수행할 수 있습니다.
Boolean(""); // -> false
배열은 진실이므로 이중 NOT 연산자는 true를 출력합니다. 그런 다음 더하기 문자는 true를 숫자 표현으로 변환합니다: 1.
!![]; // -> true
+true; // -> 1
이 표현은 명확하게 쓰면 더 명확해질 수도 있습니다.
Number(Boolean([])); // -> 1
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 에게 모든 공을 돌립니다. 더 자세한 설명(대신 사용할 수 있는 대체 함수 포함)은 그의 웹사이트를 확인하세요.
추상적 동등 비교 규칙에 따라 , 두 값은 비교 시 모두 숫자로 변환됩니다.
Number(true); // -> 1
Number("true"); // -> NaN
1 == NaN; // -> false
010은 JavaScript에서 8진수로 처리됩니다. 따라서 값은 8진수입니다. MDN 웹 문서는 8진수에 대한 간략한 설명을 제공합니다 .
010; // -> 8
03; // -> 3
8 - 3; // -> 5
원하시면 8진수를 사용해도 됩니다.
01111111111111111; // -> 40210710958665
그런데 앞에 오는 0의 개수는 중요하지 않습니다.
010 === 0000000010; // -> true
이 두 개의 빈 문자열은 모두 0으로 변환됩니다.
Number(""); // -> 0
0 - - 0; // -> 0
이렇게 쓰면 표현이 조금 더 명확해질 수도 있을 것 같습니다.
+"" - -"";
+0 - -0;
여러분을 혼란스럽게 하려고 빼기 기호와 빈 문자열 사이에 공백을 두었지만 빼기 기호 사이의 공백 자체도 중요하다는 점에 유의하세요.
-(공백)-""; // -> 0
--""; // -> SyntaxError
Null은 숫자형 표현인 0으로 변환됩니다.
Number(null); // -> 0
0 + 0; // -> 0
이는 또한...
null === false; // -> false
... 이건 사실이에요:
+null === +false; // -> true
0/0 방정식에 대한 의미 있는 숫자적 답이 없으므로 출력은 단순히 NaN 입니다 .
isNaN(0/0); // -> true
JavaScript는 이 두 값을 모두 무한대로 취급하고, 무한대는 무한대와 같습니다. 무한대에 대해 자세히 알아보세요.
1/0; // -> Infinity
10 ** 1000; // -> Infinity
Infinity > Infinity; // -> false
지수 연산자 ** 는 기본적으로 Math.pow 함수 와 동일 합니다 .
10 ** 1000; // -> Infinity
Math.pow(10, 1000); // -> Infinity
첫 번째이자 유일한 구문 오류
많은 질문에 SyntaxError를 옵션으로 두고 있음
일부 사용자가 어떤 구문이 너무 이상해서 허용될 수 없다고 생각하기를 바래서 실제로 SyntaxError를 발생시키는 표현식을 추가
그런데 일부 전역 변수와 함수는 구문 오류를 발생시키지 않는다.
true++; // -> SyntaxError
1++; // -> SyntaxError
"x"++; // -> SyntaxError
null++; // -> SyntaxError
undefined++; // -> NaN
$++; // -> NaN
console.log++; // -> NaN
NaN++; // -> NaN
물론, 완전히 명확하게 하기 위해 말씀드리자면, 이는 유효한 구문입니다.
let _true = true;
_true++;
_true; // -> 2
덧셈 연산자 (+)는 숫자와 문자열에 모두 사용되는 반면, 뺄셈 연산자 (-)는 문자열에 용도가 없으므로 JavaScript는 이를 숫자 간의 연산으로 해석합니다. 빈 문자열은 0으로 강제 변환됩니다.
Number(""); // -> 0
0 - 1; // -> -1;
문자열 내부에 공백(또는 그 이상)이 있는 경우에도 이는 여전히 사실입니다.
" " - 1; // -> -1;
그러나 덧셈 연산자를 사용하면 문자열 연결을 우선합니다.
"" + 1; // -> "1";
null은 0으로 강제 변환됩니다.
Number(null); // -> 0
0 - 0; // -> 0
0 + "0"; // -> "00"
만약 질문에 뺄셈 연산자만 사용했다면 결과는 달랐을 것입니다.
(null - 0) - "0"; // -> 0
JS가 너무 이상해서 문자열 리터럴 "true"를 부울 true의 숫자 표현으로 변환할 것이라고 생각할 수도 있습니다. 하지만 그렇게 이상하지는 않습니다. 실제로 일어나는 일은 문자열을 숫자로 변환하려고 시도하다가 실패하는 것입니다.
Number("true"); // -> NaN
엄숙한 느낌표(논리적 NOT 연산자라고도 함)를 부울이 아닌 값 앞에 붙이면 부울 함수가 변환하는 것과 반대되는 부울 값으로 변환됩니다.
5는 true입니다:
Boolean(5); // -> true
!!5; // -> true
물론, 참의 반대는 거짓이며, 거짓은 0으로 강제 변환됩니다.
!5; // -> false
+false; // -> 0
0 + 0; // -> 0
이 질문은 질문 3과 밀접하게 연관되어 있습니다. 다시 말하지만, 매우 단순화된 답변은 JavaScript가 배열을 문자열로 변환한다는 것입니다. 이 동작을 설명하는 리소스를 찾으려면 오른쪽의 3을 클릭하세요.
[].toString(); // -> ""
"" + ""; // -> ""
또한, 질문 2에 대한 설명에서 언급했듯이, 이 표현은 끝에 쉼표가 있어도 동일합니다.
[] + [] === [,] + [,]; // -> true
이처럼 배열은 다르지만 둘 다 빈 문자열로 변환됩니다.
[].length; // -> 0
[,].length; // -> 1
[].toString() === [,].toString(); // -> true
물론, 이것도 사실입니다.
Number([]) === Number([,]); // -> true
JavaScript는 이러한 작업을 왼쪽에서 오른쪽으로 실행합니다. 숫자 3을 문자열 3에 더하면 문자열 연결이 우선합니다.
1 + 2; // -> 3
3 + "3"; // -> "33"
연산은 왼쪽에서 오른쪽으로 실행되므로 문자열을 포함한 연산이 첫 번째 연산인지 두 번째 연산인지에 따라 출력 결과가 크게 달라집니다.
"1" + 2 + 3; // -> "123"
1 + "2" + 3; // -> "123"
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
false는 숫자로 변환될 수 있지만 undefined는 숫자로 변환될 수 없습니다.
Number(undefined); // -> NaN
Number(false); // -> 0
NaN + 0; // -> NaN
그러나 undefined는 false로 표현 됩니다 .
!!undefined === false; // -> true
즉, 다음과 같이 undefined와 false를 추가할 수 있습니다.
!!undefined + false; // -> 0
여러분은 if 문에서만 논리적 AND 연산자를 사용했을 가능성이 있지만 , 단독으로 사용되면 실제로 피연산자 중 하나의 값을 반환합니다. 첫 번째 표현식이 참이면 두 번째 표현식을 반환합니다. 그렇지 않으면 첫 번째 표현식을 반환합니다. 빈 문자열은 거짓이므로 첫 번째 피연산자를 반환합니다.
"" && -0; // -> ""
-0 && ""; // -> -0
5 && 3; // -> 3
0 && 3; // -> 0
피날레는 이 퀴즈에서 다룬 기괴한 구문 중 일부를 결합합니다. 위의 설명에서 이미 모든 동작을 설명했지만, 곱셈 연산자(*)는 비어 있는 문자열을 숫자로 변환합니다: 0.
+!!NaN; // -> 0
+""; // -> 0
-[,]; // -> -0
모두 합치면 다음과 같습니다.
0 * 0 - -0; // -> 0