lodashソース分析のNaNはNaNではありません.


片思いの純粋さは、結果を求めず、自分を一方的な関係に閉じ込めてしまうことにあります.
——梁文道『ひそかに思いを寄せてのぞきます』
本文はlodashのソースコードの第五編を読むために、後続の文章はこの倉庫に更新されます.スターを歓迎します.
git bookも同時に倉庫の更新ができます.gitbookアドレス:pocket-lodash
この分析はeq関数です.
役割と使い方eq関数は、2つの値が等しいかどうかを比較するために使用される.遵守しているのはサマーヴェルエZero仕様です.
var obj1 = {test: 1}
var obj2 = {test: 1}
var obj3 = obj1
_.eq(1,1) // true
_.eq(+0, -0) // true
_.eq(obj1, obj3) // true
_.eq(obj1, obj2) // false
_.eq(NaN, NaN) // false
いくつかの比較規範
SameValue NonNumber
この仕様で規定されている比較値xおよびyは、Numberタイプではなく、コピー仕様は以下の通りである.
  • xのタイプはNumberタイプ
  • ではありません.
  • yのタイプはxのタイプと一致しています.
  • もしxのタイプがUndefinedであれば、true
  • に戻る.
  • もしxのタイプがNullであれば、true
  • に戻る.
  • は、xのタイプがStringであり、xyの長さ及び符号化が同じであれば、trueに戻り、そうでなければfalse
  • に戻る.
  • は、xのタイプがBooleanであり、xyと同じtrueであるか、または同じfalseであるか、trueに戻り、そうでなければfalse
  • に戻る.
  • は、xのタイプがSymbolであり、xyとが同じSymbolの値を持っている場合、trueに戻り、そうでなければfalse
  • に戻る.
  • は、xおよびyが同じオブジェクトを指す場合、trueに戻り、そうでなければfalse
  • に戻る.
    Strict Equality Compparison
    js中の全等(===)はこの規定に従います.
  • は、xyのタイプが異なる場合、false
  • に戻る.
  • の場合、xNumberタイプである:
  • a.xNaNであれば、false
  • に戻る.
  • b.yNaNであれば、false
  • に戻る.
  • c.もしxyの数値が一致したら、true
  • を返します.
  • d.x+0であり、y-0である場合、true
  • に戻る.
  • e.x-0y+0であれば、true
  • に戻る.
  • f.false
  • を返します.
  • はSameValueNonNumberの結果によって
  • に戻ります.
    SameValue
    仕様は以下の通りです
  • は、xyのタイプが異なる場合、false
  • に戻る.
  • もしxのタイプがNumberだったら
  • a.xNaNyNaNであれば、true
  • に戻る.
  • b.x+0であり、y-0である場合、false
  • に戻る.
  • c.x-0であり、y+0である場合、false
  • に戻る.
  • d.もしxyの数値が一致したら、true
  • を返します.
  • e.false
  • を返します.
  • はSameValueNonNumberの結果によって
  • に戻ります.
    SameValue Zero
    これはeq準拠の仕様です.
  • は、xyのタイプが異なる場合、false
  • に戻る.
  • もしxのタイプがNumberだったら
  • a.xNaNyNaNであれば、true
  • に戻る.
  • b.x+0であり、y-0である場合、true
  • に戻る.
  • c.x-0であり、y+0である場合、true
  • に戻る.
  • d.もしxyの数値が一致したら、true
  • を返します.
  • e.false
  • を返します.
  • はSameValueNonNumberの結果によって
  • に戻ります.
    小結:SameValueNonNumberは基本であり、Strict Equality ComparisonSameValueSameValueZero+0に対してのみ違いがあります.
    ソース分析-0のソースコードを見てください.
    function eq(value, other) {
      return value === other || (value !== value && other !== other)
    }
    実はNaNのソースコードはこのようにしかありません.eqが準拠しているのはeq規格です.ソースコードを分解して、どのように規格に合っているかを見てください.
    まず、第一部を見ます.
    value === other
    このように、該当するのはeq仕様で、比較によって、SameValueZeroStrict Equality ComparisonStrict Equality Comparisonに対してのみ区別があることが分かります.SameValueZeroは、NaNStrict Equality Comparisonが全部xである場合でも、yに戻り、NaNに戻ります.しかし、falseNaN === NaNfalseの両方がSameValueZeroであるときに戻ってくる規定です.したがって、xに基づいてyを処理するだけでよい.
    以下の部分は処理NaNである.
    (value !== value && other !== other)
    jsにおいては、trueと自身だけが等しくない.2つの比較が必要な値がすべて自身と等しくない場合、この2つの値はいずれもStrict Equality Comparisonであり、NaNに戻ることを示す.
    このようにして、NaNの比較に従って実現される.
    Object.is()を使ってもいいですか?NaNNaNに戻るので、trueも同様に、
    function eq(value, other) {
      return value === other || Object.is(value, other)
    }
    SameValueZeroも同じかどうかの比較ですが、Object.is(NaN, NaN)trueに戻り、eqに従っているので、Object.isを直接Object.is(+0, -0)に置き換えることはできません.
    isNaNを使ってもいいですか?falseの大域的な方法もあり、1つの値がSameValueであるかどうかを判断するために使用されてもよい.例えばObject.iseqに戻りますが、isNaNは次のような形に変えられますか?
    function eq(value, other) {
      return value === other || (isNaN(value) && isNaN(other))
    }
    いけません.NaNには、着信パラメータがisNaN(NaN)タイプでない場合、trueタイプに変換してからeqかどうかを判断する奇異な行動がある.したがって、isNaNのように戻ってきたのもNumberであり、文字列Numberは、まずNaNに変換されてから判断されるので、これは私たちが望む結果ではない.
    Number.isNaN()を使ってもいいですか?isNaN('notNaN')の欠陥を修復するために、truenotNaNオブジェクトにNaN方法を拡張し、isNaNであるときだけes6に戻るので、Numberで安全であると判断する.したがって、isNaNも以下のように変更することができる.
    function eq(value, other) {
      return value === other || (Number.isNaN(value) && Number.isNaN(other))
    }
    参照
  • ECMAScript® 2016 Language Specification
  • MDN:Number.isNaN()
  • MDN:isNaN()
  • License
    署名-非商業的使用-演繹禁止4.0国際(CC BY-NC-ND 4.0)
    最後に、すべての文章が同時にWeChat公衆番号に送られます.ご注目ください.ご意見をどうぞ.
    対角線の反対側