はじめに
今回は、以下のjsisweird様のサイトの問題を解いて、非常に面白いなと思い復習がてら書いた記事になります。
ここから式と選択肢、回答を順に羅列していきますので、よければ正解を予想しながら読み進めてみてください!
1 true + false
"truefalse"
1
NaN
SyntaxError
回答
正解は`1`になります。演算子 + は両辺をプリミティブ型に変換して計算しようとします。
以下MDNより引用
一方が文字列の場合、もう一方のオペランドも文字列に変換され、連結されます。_
もし両方が長整数であれば、長整数同士の加算が行われます。一方が長整数で、もう一方が長整数でない場合、TypeError 例外が発生します。
そうでない場合は、両辺が数値へ変換され、数値同士の加算が行われます。
ブール値は数値に型変換されますので、結果としては1になります。
Number(true); // -> 1
Number(false); // -> 0
1 + 0; // -> 1
2 [,,,].length
0
3
4
SyntaxError
回答
正解は`4`になります。[,,,]
は3つの空スロットを持つ配列を出力します。最後のカンマはTrailing_commas(末尾のカンマ)と言われるらしいです。
参考 :https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Trailing_commas
さらに、以下のような意味のわからない例も記載してありました。あまりにも複雑。
[,] + [,]; // -> ""
[] + [] === [,] + [,]; // -> true
[,,,] + [,,,]; // -> ",,,,"
([,,,] + [,,,]).length === [,,,,].length; // -> true
3 [1, 2, 3] + [4, 5, 6]
"123456"
"1,2,34,5,6"
"1,2,3,4,5,6"
NaN
回答
正解は`"1,2,34,5,6"`になります。配列は文字列に変換され、連結されます。
参考記事として以下の二つが記載されていました。
https://stackoverflow.com/questions/17977232/php-query-string-url-issue/17977274#17977274
4 0.2 + 0.1 === 0.3
true
false
NaN
SyntaxError
回答
正解は`false`になります。 こちらは比較的有名な気がしますね。浮動小数点数を比較する際に起こる問題です。
https://stackoverflow.com/questions/588004/is-floating-point-math-broken
5 10,2
10.2
10
2
20
回答
正解は`2`になります。 カンマ演算子は単に最後のオペランドの値を返すらしいです。10, 2; // -> 2
1, 2, 3, 4; // -> 4
42, "pineapple", true; // -> true
6 !!""
true
false
undefined
SyntaxError
回答
正解は`false`になります。二重否定と呼ばれる記法です。
複数の否定演算子を連続して使用することで、明示的にあらゆる値を対応する論理型プリミティブ
に変換することができます。
今回の例で言うと、""
自体がfalsyな値ですので、その否定の否定でfalse
になります。
n1 = !!true; // !!truthy は true を返す
n2 = !!{}; // !!truthy は true: *あらゆる*オブジェクトは真値になります...
n3 = !!new Boolean(false); // ... .valueOF() が false の Boolean オブジェクトであっても
n4 = !!false; // !!falsy は false を返す
n5 = !!""; // !!falsy は false を返す
n6 = !!Boolean(false); // !!falsy は false を返す
7 +!![]
true
false
0
1
回答
正解は`1`になります。 ここまでの問題の知識で解けますね。 `[]`はオブジェクトなのでtruthyな値です。その二重否定でtrueが取れ、`+true`となります。 +の両辺は数値型に変換されますので、結果`+1`となります
8 parseInt(0.0000005)
0
1
5
NaN
回答
正解は`5`になります。parseInt()
は引数を文字列に変換し、次に数字に変換します。0.0000005が文字列に変換されると次のようになります。
String(0.0000005); // -> "5e-7"
parseInt関数はその文字列の最初の文字、5だけを返す。となるらしいです。
これはわからなかった...
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/parseInt
9 true == "true"
true
false
undefined
SyntaxError
回答
正解は`false`になります。==(抽象的な等価比較)は、比較する際に両辺を数値へ変換します。
なので、1 == NaN
となり、falseになります。
10 010 - 03
7
5
3
NaN
回答
正解は`5`になります。010
はJavaScriptによって8進数として扱われます。したがって以下のようになります。
010; // -> 8
03; // -> 3
8 - 3; // -> 5
11 "" - - ""
""
0
NaN
SyntaxError
回答
正解は`0`になります。 空文字列はどちらも0に変換されますので、`0 - 0`となります。
12 null + 0
0
"null0"
NaN
TypeError
回答
正解は`0`になります。 nullは数値に変換され、falsyな値なので0となります。 結果`0 + 0`となります。
13 0 / 0
0
Infinity
NaN
SyntaxError
回答
正解は`NaN`になります。0/0という方程式には意味のある数値的な答えはないので、出力は単にNaNとなります。
14 1 / 0 > 10 ** 1000
true
false
NaN
SyntaxError
回答
正解は`false`になります。以下のような値はInfinity
となります。
1/0; // -> Infinity
10 ** 1000; // -> Infinity
Infinity > Infinity; // -> false
また、10 ** 1000
もInfinity
となり、結果false
となるそうです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Infinity
15 true++
1
2
NaN
SyntaxError
回答
正解は`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
"1"
"-1"
-1
NaN
回答
正解は`-1`になります。 加算演算子(+)は数値と文字列の両方に使用されますが、減算演算子(-)は文字列には使用されないため、JavaScriptはこれを数値間の演算と解釈します。結果0 - 1
となります。
17 (null - 0) + "0"
"null0"
"00"
0
NaN
回答
正解は`00`になります。 ここまでの知識を使用して解けますね。null - 0
はnullが数値に変換されて0、(0 - 0)
で 0です。
加算演算子のどちらか一方が文字列の場合、両辺文字列として連結されるので"0" + "0"
となり"00"
になります。
18 true + ("true" - 0)
1
2
NaN
SyntaxError
回答
正解は`NaN`になります。 ここまでの知識を使用して解ける...と思いきや、"true"は数値型に変換できないので、`NaN`になります。
19 !5 + !5
0
10
25
NaN
回答
正解は`0`になります。論理NOT演算子(!)は非ブール値をそのブール値の反対に変換します。
5はbool値で表すとtrueなので、その否定でfalseになります。
結果false + false
になり、0 + 0
で0
になります。
20 [] + []
の結果は何ですか?
[]
[ , ]
""
NaN
回答
正解は`""`になります。 前述の通り、JavaScriptは配列を文字列に変換します。 結果`"" + ""`となり、文字列なので連結が行われて`""`になります。
21 1 + 2 + "3"
6
"123"
"33"
NaN
回答
正解は`33`になります。計算は左から右に行われるので、まず1 + 2
が計算されます。
その次に3 + "3"
が実行されます。
22 typeof NaN
"number"
"nan"
"undefined"
"object"
回答
正解は`number`になります。 ECMAScriptの仕様書では、NaNはIEEE 754の「数値でない」値である数値値として説明されているそうです。
23 undefined + false
"undefinedfalse"
0
NaN
SyntaxError
回答
正解は`NaN`になります。 `undefined`は数値に変換できません。 しかし、`!!undefined`はfalseとなります。
24 "" && -0
true
false
""
-0
回答
正解は`""`になります。 Reactを使用している人には簡単だったかもしれませんね。 &&演算子は最初の式がtruthyである場合、2番目の式を返します。そうでない場合、最初の式を返します。空の文字列はfalsyであるため、最初のオペランドを返します。https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Logical_AND
25 +!!NaN * "" - - [ , ]
0
"0"
NaN
I give up
回答
正解は`0`になります。 今までの問題の総集編のような問題でした。 乗算演算子は、空文字列を数値に等価な0に変換するという仕様があるので0となります。おわりに
最後までお読みいただきありがとうございました!
演算子と型はJSの基礎的な部分ですが、知らない使用も多くまだまだ学ばなければならないと改めて思いました。
その一方、jsisweird様のトップページに以下のような記載があります。
この構文のほとんどは、おそらく、そして願わくば、日常生活で使用しないものです。
今回出題されたいくつかの構文は、たとえコードを短くかけるようになっても直感的でなかったり、わかりづらくしてしまうこともあると感じたので使用には注意が必要かもしれません。
今回の記事の引用元