アンダースコアからのコード行を次に示します。この行のプラスプレフィックスは何ですか?
if (obj.length === +obj.length) { // plus prefix?
アンダースコアからのコード行を次に示します。この行のプラスプレフィックスは何ですか?
if (obj.length === +obj.length) { // plus prefix?
記号を追加すると+、次のように変数が数値に効果的に変換されます。
+"1" === 1;
ただし、
+"1" === "1"; // FALSE
+"1" == "1"; // TRUE
これは、==がそのオペランドを同じ型に変換するのに対し、変換し===ないためです。
つまり、テストは次のことを意味します。
obj.length === +obj.length
obj.length基本的に、数値かどうかをテストしようとしています。
Underscore では、このコードは不明な型の変数に呼び出されたプロパティがあるlengthかどうか、およびそれが数値かどうかを判断しようとしています。これらが両方とも真である場合、変数が配列である場合は、変数を反復処理できると想定されています。
OPのコードには多くのバグが含まれていることに注意してください。そのうちの少なくとも1つは、何かが配列(または配列のようなもの)であるかどうかを検出するこのアプローチです。次のオブジェクトは問題を引き起こします。
var footballField = {
covering: "astroturf",
condition: "muddy",
length: 100
};
私は上記のアプローチを提唱しているわけではありません...他の誰かのアプローチを説明しているだけです。
プラスのプレフィックスは、変数を数値に変換します。基本的に、これobj.length === +obj.lengthは obj.length が実際に数値であるかどうかの健全性チェックです。obj.lengthが数値ではなく、たとえば string"foo"であった場合、として出力される"foo" === +"foo"ため、 false と同等になります。+"foo"NaN
+ プレフィックスは、値を数値に変換します。
これにより、 の値がobj.lengthになりますNumber。length基本的にこれは、配列のようなオブジェクトのデフォルト値がオーバーライドされていないことを確認して、適切に反復できるようにするために行われます。
breakerこのコンテキストでは何もしません。同等の比較がなくても、別の空のオブジェクトでさえ ..と比較すると に{}評価されるからです。falsebreaker
ただし、関数の外部でbreaker定義されているため、そのコンテキストでは使用されません。これは、ここに表示されているものとは異なるように見えます。代わりに、他のループ メソッドから強制的に「中断」するために使用されます。.each
_.every = _.all = function(obj, iterator, context) {
/* snip */
if (!(result = result && iterator.call(context, value, index, list)))
return breaker;
「every」で結果が真実でない場合は、すぐに中断したいことがわかります。 _.everyを呼び出し、それ自体と比較したときに true になる_.eachものを返し、すぐに中断できるようにします。breaker
lengthオブジェクトにプロパティがない場合(Objectではなく、通常のArray)、呼び出しobj.lengthは を返しundefinedます。未定義のテストはより明確になりますが、実装者は最初にそれを数値に変換することを選択し (したがって、 になりますNaN)、元の値と比較します (厳密な比較を使用して、確実に が得られるようにしますfalse)。
更新:他の人が指摘したように、このコードはArrays だけでなく、「配列のような」オブジェクト (つまり、数値lengthプロパティと数値インデックスを持つオブジェクト) にも関係しているようです。そのような場合、 をテストするinstanceof Arrayだけでは十分ではありません (別のタイプundefinedの but が存在する可能性があるため、 をテストするだけでは最適なオプションではない可能性がありますlength)。