アンダースコアからのコード行を次に示します。この行のプラスプレフィックスは何ですか?
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
このコンテキストでは何もしません。同等の比較がなくても、別の空のオブジェクトでさえ ..と比較すると に{}
評価されるからです。false
breaker
ただし、関数の外部で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
)。
更新:他の人が指摘したように、このコードはArray
s だけでなく、「配列のような」オブジェクト (つまり、数値length
プロパティと数値インデックスを持つオブジェクト) にも関係しているようです。そのような場合、 をテストするinstanceof Array
だけでは十分ではありません (別のタイプundefined
の but が存在する可能性があるため、 をテストするだけでは最適なオプションではない可能性がありますlength
)。