【undersscoreソースの解読】JavaScriptでは、2つの要素が「同じ」かどうかを判断します.

4965 ワード

Why under score
最近はundersscore.jsのソースコードを見始めました.undersscore.jsのソースコードの解読を2016年の計画に入れました.
いくつかの有名な枠组みのソースコードを読むと、まるでみんなと対话するように、多くのことを学ぶことができます.なぜアンダースコアですか?最も主要な原因はアンダースコアが短くて精悍(約1.5 k行)で、100以上の有用な方法を実装しています.結合度が低く、一つ一つの方法で読むのに適しています.ビルのようなJavaScript初心者に適しています.そこから、void 0をundefinedの代わりに使って、undefinedを書き換えるなどのテクニックを身につけるだけでなく、変数型の判断や関数の節流や関数の手ぶれなど、よく使われる方法を学ぶことができます.また、多くのブラウザに対応するhackを学ぶことができます.また、作者の全体的な設計構想やAPI設計の原理(後方互換性)を学ぶことができます.
その後、スレ主は一連の文章を書いて、皆さんとソースの読み取りで学んだ知識を共有します.
  • undersscore-1.8.3ソース解読プロジェクトの住所https://github.com/hanzichi/underscore-analysis
  • undersscore-1.8.3ソースの全文コメントhttps://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js
  • undersscore-1.8.3ソース解読シリーズの文章https://github.com/hanzichi/underscore-analysis/issues
  • いらっしゃいませ.(興味があれば、star&watchを歓迎します.)あなたの注目はビルの続けて書く動力です.
    _.isequal
    本文はJavaScriptの中でどのように二つのパラメータが「同じ」であるかを判断するか、すなわちunderscoreのソースコードの中の_.isequal方法この方法はunderscoreのソースコードの中で最も複雑な方法を実現すると言ってもいいです.
    では、私が言っている「同じ」とはどういう意味ですか?栗を例に挙げると、1new Number(1)はequalとされ、[1][1]はequalとされています.もちろん、2つの参照は同じ対象です.
    じゃ、これはどうデザインしますか?isEqual関数は?私達はundersscoreのソースコードに従って、一歩ずつその実現を見にきます.後の文では、比較した二つのパラメータはaとbと仮定します.
    まず、a === bと判断します.trueの場合は、aとbは基本タイプです.2つの基本タイプの値は同じです.2つは2つの参照タイプです.つまり、参照タイプの参照は同じです.a === bがtrueなら、aとbはequalということですか?実は99%の場合は、0と0というスペシャリストcaseも考慮しなければなりません.0 === -0はtrueです.0と-0はunequalとされています.原因は、参照できます.http://wiki.ecmascript.org/doku.php?id=harmony:egal.
    この部分のコードはこのように表してもいいです.
    // Identical objects are equal. `0 === -0`, but they aren't identical.
    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
    // a === b  
    //      `0 === -0`    special case
    // 0   -0    
    //              
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    
    次の場合はa !== bの場合です.
    aとbの中にnullかundefinedがあれば、特別に判定して、比較を続けなくてもいいです.ソースの実現:
    // A strict comparison is necessary because `null == undefined`.
    //    a   b      null(   undefined)
    //    a === b
    if (a == null || b == null) return a === b;
    
    個人的にはここに書いたのが少し余分だと思います.上の判断でフィルタリングしますので、a==bはfalseに戻ります.
    ok、続けます.これからはaとbのタイプによって判断します.もしタイプが違ったら、引き続き判断する必要がありません.変数の種類はどうやって取得しますか?そうです.不思議なObject.prototype.toString.callです.
    もしタイプがRegExpとStringなら、aとbをそれぞれ文字列に変えて比較できます.
    var a = /a/;
    var b = new RegExp("a");
    
    console.log(_.isEqual(a, b));  // => true
    
    実はアンダースコアの内部ではこう判断されています.
    var a = /a/;
    var b = new RegExp("a");
    
    var _a = '' + a; // => /a/
    var _b = '' + b; // => /a/
    
    console.log(_a === _b); // => true
    
    Numberタイプなら?ここにまたspecial caseがあります.つまりNaNです.ここではNaNはNaNと同じだけで、他のNumberタイプとはunequalであると規定している.ここでは引用の種類を基本のタイプに変えます.次のコードを見てください.
    var a = new Number(1);
    console.log(+a); // 1
    
    そうです.+を追加すれば解決されます.他のものは分かりにくくないです.全部注釈に入っています.
    // `NaN`s are equivalent, but non-reflexive.
    // Object(NaN) is equivalent to NaN
    //    +a !== +a 
    //    a    NaN
    //    b      NaN   
    if (+a !== +a) return +b !== +b;
    
    // An `egal` comparison is performed for other numeric values.
    //     NaN   
    //      0    
    //   +a   Number()         
    //    a   0,   1 / +a === 1 / b
    //      +a === +b
    return +a === 0 ? 1 / +a === 1 / b : +a === +b;
    
    //    a   Number   
    //     NaN    special number
    // NaN   NaN     equal
    
    次にDateとBooleanの二つのタイプを見ます.Numberタイプと同様に、+を基本タイプの数字に変換することもできます.次のコードを見てください
    var a = new Date();
    var b = true;
    var c = new Boolean(false);
    
    console.log(+a); // 1464180857222
    console.log(+b); // 1
    console.log(+c); // 0
    
    とても簡単です.実は+new Date()(または+new Dateとも書くことができます.)は現在の時間と1970年1月1日0時のミリ秒数(milisecond)を取得しています.タイムスタンプはこのデータを1000で割って、つまり秒数です.canvasでアニメを作る時、私はよく+new Dateをタイムスタンプとして使います.
    そして、aとbがともにDateタイプまたはBooleanタイプであれば、+a === +bを使ってequalかどうかを判断することができます.
    プログラムは続いて行って、私達は引き続き見て、まだ2種類の重要なタイプがあるようですが、判断していませんか?そう、ArayとObject!undersscoreはこれを再帰的な方法で展開して比較する.
    やはり栗を挙げましょう.例を挙げると直感的です.
    a,bを以下のように仮定する.
    var a = {name: "hanzichi", loveCity: [{cityName: "hangzhou", province: "zhenjiang"}], age: 30};
    var b = {name: "hanzichi", loveCity: [{cityName: "hangzhou", province: "zhenjiang"}], age: 25};
    
    まずa、bは対象で、それぞれキーの値を比較してもいいです.もしキーの値が違うと(或いはキーの値がaとbに対して一つもないということです)、aとb unequalです.行列なら?一つの元素を比較します.配列はオブジェクトをネストすることができますので、オブジェクトのvalueは配列かもしれません.
    それとも上記の例で、私達はそれを三回に分けて比較して、それぞれ三つのkeyのvalueの値が同じかどうかを比較します.loveCityというkeyのvalueについては、そのvalueはまた配列であるため、このvalueを比較関数に導入し、この比較の結果、最後の比較結果を判断します.再帰はこのようにして、大きなものを一つずつ小さく分解し、小さな結果によって大きな結果をまとめます.
    最後にコード位置を与えます.についてisEqualメソッドのソースコードは、みんなが参照することができます.https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L1094-L 1190