![](https://habrastorage.org/getpro/habr/post_images/ade/9bb/322/ade9bb322bafb763c7f503a383036a27.jpg)
正月休みの後、私はすでにコミュニティがJavaScriptのパズルの状況を通して心を広げることを提案しました 。 その投稿からかなりの時間が経過し、他にも多くの休暇がありましたので、タスクの新しい部分について考えることをお勧めします。
前回のように、この振る舞いがネタバレの下で論理的である理由の説明と私自身のバージョンの説明を隠します。 すぐに、私のバージョンの揺るぎない真実を装わないように予約してください。 ECMAScript 5仕様の優れたロシア語の翻訳は、これを解決するのに役立ちます。
1.人生の主な問題、宇宙とすべて
"3" -+-+-+ "1" + "1" / "3" * "6" + "2"
解決策
前回の投稿ですでに知っているように、+演算子は文字列の連結、または数値への加算または縮小を実行します。 つまり
ご想像のとおり、5ではありません。
さらに、式に単項演算子「+」または「-」をスローして、その符号を変更し、物事をより美しく読みやすくすることができます。
上記のすべてを考えると:
次に、操作の優先順位を思い出してください:/ * +
"3" -+-+-+ "1" + "1" / "3" * "6" + "2" == "42"
前回の投稿ですでに知っているように、+演算子は文字列の連結、または数値への加算または縮小を実行します。 つまり
“3” + 2 == “32”
ご想像のとおり、5ではありません。
さらに、式に単項演算子「+」または「-」をスローして、その符号を変更し、物事をより美しく読みやすくすることができます。
上記のすべてを考えると:
+ “1” === 1 -+ “1” === -1 +-+ “1” === -1 … -+-+-+ === -1 "3" -+-+-+ "1" === 2 //
次に、操作の優先順位を思い出してください:/ * +
“1”/”3” === 0.3333… “1” / ”3” * ”6” === 2 2 + 2 === 4 4 + “2” === “42”
2.マキシマリズム
Math.max(3, 0); Math.max(3, {}); Math.max(3, []); Math.max(-1, [1]); Math.max(-1, [1, 4]); Math.max(3, true); Math.max(3, 'foo'); Math.max(-1, null); Math.max(-1, undefined);
解決策
ここではすべてが簡単です。
{}に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して"[object Object]"を取得します。
結果の文字列toNumberに対して実行し、 NaNを取得します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
[]に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して「」を取得します。
結果の文字列toNumberに対して実行し、0を取得します。
3> 0
[1]に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して「1」を取得します。
結果の文字列toNumberに対して実行し、1を取得します。
-1 <1
[1,4]に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して「1.4」を取得します。
結果の文字列toNumberに対して実行し、 NaNを取得します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
trueに対してtoNumberを実行してみてください:
valueOfを実行し、これがプリミティブかどうかを確認します-はい、その後
3> 1
'foo'の場合、 toNumberはNaNを返します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
Math.max(3, 0); // 3
ここではすべてが簡単です。
Math.max(3, {}); // NaN
{}に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して"[object Object]"を取得します。
結果の文字列toNumberに対して実行し、 NaNを取得します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
Math.max(3, []); // 3
[]に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して「」を取得します。
結果の文字列toNumberに対して実行し、0を取得します。
3> 0
Math.max(-1, [1]); // 1
[1]に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して「1」を取得します。
結果の文字列toNumberに対して実行し、1を取得します。
-1 <1
Math.max(-1, [1, 4]); // NaN
[1,4]に対してtoNumberを実行してください:
valueOfを実行し、これがプリミティブかどうかを確認します-いいえ、
toStringを実行して「1.4」を取得します。
結果の文字列toNumberに対して実行し、 NaNを取得します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
Math.max(3, true); // 3
trueに対してtoNumberを実行してみてください:
valueOfを実行し、これがプリミティブかどうかを確認します-はい、その後
toNumber(true) === 1
3> 1
Math.max(3, 'foo'); // NaN
'foo'の場合、 toNumberはNaNを返します。
NaNを受信した場合、 Math.max()は常にNaNを返します。
Math.max(-1, null); // 0
toNumber(null) === 0 -1 < 0
Math.max(-1, undefined); // NaN
toNumber(undefined) === NaN
NaNを受信した場合、 Math.max()は常にNaNを返します。
3.生活コンマ
[,,,].join() [,,,undefined].join()
非表示のテキスト
ここでは、フラナガンのみを参照できます。 7.1:
「配列リテラルに値のない連続した複数のコンマが含まれている場合、スパース配列が作成されます。 このような欠損値に対応する要素は配列にありませんが、それらにアクセスすると、未定義の値が返されます。
「配列リテラルの構文により、オプションの末尾コンマを挿入できます。」
なぜこれが行われるかは私には明らかではありません。 最後の投稿のコメントで、これは機能として提示されました。 私の意見では、これはまだコードのエラーによるブラウザの松葉杖です。
[,,,].join() // ",," [,,,undefined].join() // ",,,"
ここでは、フラナガンのみを参照できます。 7.1:
「配列リテラルに値のない連続した複数のコンマが含まれている場合、スパース配列が作成されます。 このような欠損値に対応する要素は配列にありませんが、それらにアクセスすると、未定義の値が返されます。
「配列リテラルの構文により、オプションの末尾コンマを挿入できます。」
なぜこれが行われるかは私には明らかではありません。 最後の投稿のコメントで、これは機能として提示されました。 私の意見では、これはまだコードのエラーによるブラウザの松葉杖です。
4.トレジャーマップ
Array(20).map(function(elem) { return 'a'; });
非表示のテキスト
1つの引数でArrayコンストラクターを呼び出すと、20個の要素の配列は作成されませんが、20個の長さの配列が作成されます。また、 mapメソッドは、最初に転送された配列の長さと等しい長さの空の配列を作成し、次に転送された配列の各要素のコールバックを呼び出します この場合、配列には要素がなく、メソッドは元の配列と同じ長さの空の配列を返します。
Array(20).map(function(elem) { return 'a'; }); // Array of undefined x 20
1つの引数でArrayコンストラクターを呼び出すと、20個の要素の配列は作成されませんが、20個の長さの配列が作成されます。また、 mapメソッドは、最初に転送された配列の長さと等しい長さの空の配列を作成し、次に転送された配列の各要素のコールバックを呼び出します この場合、配列には要素がなく、メソッドは元の配列と同じ長さの空の配列を返します。
5. Finita la comedia
isFinite(42); isFinite(1/0); isFinite(0/0); isFinite('42'); isFinite('hi'); isFinite(); isFinite(undefined); isFinite(null);
非表示のテキスト
isFiniteは引数を数値に変換し、 NaN、+ Infinityまたは-Infinityの場合、 falseを返します 。 その他の場合はすべて、 true 。
「hi」のToNumberはNaNを返し、 undefinedはNaNを返し、 nullは0を返します。
isFinite(42); // true isFinite(1/0); // false isFinite(0/0); // NaN is not finite -> false isFinite('42'); // true isFinite('hi'); // false isFinite(); // false isFinite(undefined); // false isFinite(null); // true
isFiniteは引数を数値に変換し、 NaN、+ Infinityまたは-Infinityの場合、 falseを返します 。 その他の場合はすべて、 true 。
「hi」のToNumberはNaNを返し、 undefinedはNaNを返し、 nullは0を返します。
6.実話仲間
'true' == true
非表示のテキスト
等号演算子は、最初に真、次に「真」の数値につながります。 NaN == 1であることがわかりますが、これは明らかに偽です。
'true' == true //false
等号演算子は、最初に真、次に「真」の数値につながります。 NaN == 1であることがわかりますが、これは明らかに偽です。
7.何もない
null == false !null
非表示のテキスト
nullをブールにキャストすると、すべてが明確になります。 比較に取りかかりましょう。 nullとboolの組み合わせは、仕様の11.9.3節の比較\ castオプションのいずれにも該当しないため、比較はfalseを返します 。
null == false // false !null // true
nullをブールにキャストすると、すべてが明確になります。 比較に取りかかりましょう。 nullとboolの組み合わせは、仕様の11.9.3節の比較\ castオプションのいずれにも該当しないため、比較はfalseを返します 。
8.不確実性テスト
/^[az]{1,10}$/.test(null); /^[az]{1,10}$/.test(undefined);
非表示のテキスト
nullおよびundefinedは、そのまま文字列にキャストされます。「null」および「undefined」-このような文字列は正規表現を満たします。 ところで、NaNも「NaN」になります。
/^[az]{1,10}$/.test(null); //true /^[az]{1,10}$/.test(undefined); //true
nullおよびundefinedは、そのまま文字列にキャストされます。「null」および「undefined」-このような文字列は正規表現を満たします。 ところで、NaNも「NaN」になります。
9.ゼロの否定
0 === -0 1/0 === 1/-0
非表示のテキスト
ゼロは負のゼロですが、符号付き除算では符号が考慮され、判明します
0 === -0 //true 1/0 === 1/-0 //false
ゼロは負のゼロですが、符号付き除算では符号が考慮され、判明します
Infinity === -Infinity
最後まで読んだヒーローにとって、おそらく最も興味深いパズルです。 別のネタバレの下に説明を隠したくないので、答えを出した後にdevtoolsを提供し、そこでチェックすることをお勧めします。 結果はあなたを驚かせるでしょう、そしてあなたは再び考えたいと思うでしょう。
10.スラッシュ
n = 1 /1*"\/\//.test(n + '"//') n = 1; /1*"\/\//.test(n + '"//');
非表示のテキスト
スラッシュは、正規表現、除算、コメントの3つの場合に使用できます。 ここでは、一見、正規表現のみが表示されます。 しかし、実際には、セミコロンなしでは、最初のスラッシュが除算を実行します。 したがって、除算が最初に実行され、次に結果に文字列が乗算されます。 残りのテールはコメントのままです。 数で乗算する行は削減されず、 NaNが取得されます。
n = 1 /1*"\/\//.test(n + '"//') //NaN n = 1; /1*"\/\//.test(n + '"//'); //true
スラッシュは、正規表現、除算、コメントの3つの場合に使用できます。 ここでは、一見、正規表現のみが表示されます。 しかし、実際には、セミコロンなしでは、最初のスラッシュが除算を実行します。 したがって、除算が最初に実行され、次に結果に文字列が乗算されます。 残りのテールはコメントのままです。 数で乗算する行は削減されず、 NaNが取得されます。