【サブ遅れに伴うundersscore】for…inに存在するブラウザの互換性問題を作成しますか?

8104 ワード

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/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js
  • undersscore-1.8.3ソース解読プロジェクトの住所https://github.com/hanzichi/underscore-analysis
  • undersscore-1.8.3ソース解読シリーズの文章https://github.com/hanzichi/underscore-analysis/issues
  • いらっしゃいませ.(興味があれば、star&watchを歓迎します.)あなたの注目はビルの続けて書く動力です.
    for…in
    今日はfor…inブラウザでの互換性についてお話しします.
    for…inみんなはよく知らないはずです.サイクルは列挙できる属性だけを巡ります.ArayおよびObjectのように、内蔵構造関数を用いて作成されたオブジェクトは、Object.prototypeおよびString.prototypeからエニュメレーションできない属性、例えば、StringのindexOf()方法またはObjectのtoString方法から継承されます.繰り返しオブジェクトのエニュメレート・プロパティーのすべてと、そのコンストラクタのprototypeから引き継ぎます.
    簡単な例を挙げます.
    var obj = {name: 'hanzichi', age: 30};
    
    for (var k in obj) {
      console.log(k, obj[k]);
    }
    
    //   
    // name hanzichi
    // age 30
    待ってください.for…inというのはブラウザの互換性がありますか?今まで注意したことがありません.仕事中にもこのような互換性の問題に遭遇したことがありません.確かにこのように、for…inは問題を出して、2つの条件を満たすべきで、その1つはIE<9ブラウザーの中で(また万悪のIEです!!)で、その2つは列挙される対象にいくつかの鍵盤を書き直されたので、例えばtoString.
    やはり簡単な例を挙げます.
    var obj = {toString: 'hanzichi'};
    
    for (var k in obj) {
      alert(k);
    }
    ok、chromeの中で私達alertは予想の“toString”を出して、IE 8の中で何も弾いていません.
    for…inの役割を振り返り、エニュメレート・属性を巡回してみると、IE 8はToStering「内定」をエニュメレート・属性にしていることは明らかである(書き換えられているにもかかわらず).IE 8のような環境にあるかどうかをどう判断しますか?undersscoreの中にhas EnumBug関数があります.この判断をするためのものです.
    // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
    // IE < 9       for key in ...          key
    //          `toString`   ,   key       IE < 9    for in    
    // IE < 9,{toString: null}.propertyIsEnumerable('toString')    false
    // IE < 9,    `toString`          
    var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
    コードは一目瞭然で、propertyIs Eumerable方法を使いました.
    では、どのような属性が書き換えられた後、for...inを使ってIE<9の下に列挙できませんか?次のようなものがあります
    // IE < 9      for in      key    
    var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
                        'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
    うん、constructorも漏れたはずです.
    アンダースコアはどうやって作ったのか見てみます.
    function collectNonEnumProps(obj, keys) {
      var nonEnumIdx = nonEnumerableProps.length;
      var constructor = obj.constructor;
    
      // proto        prototype
      var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
    
      // Constructor is a special case.
      // `constructor`         
      //    obj   `constructor`    key
      //     key     keys    
      //     
      var prop = 'constructor';
      if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
      
      // nonEnumerableProps      keys
      while (nonEnumIdx--) {
        prop = nonEnumerableProps[nonEnumIdx];
        // prop in obj        true  ?     ?
        // obj[prop] !== proto[prop]     key         
        if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
          keys.push(prop);
        }
      }
    }
    プロト変数はプロトタイプを保存していますが、オブジェクトのプロトタイプは、Object.prototypeで取得できます.このように、例えばtoStringを書き直して、私達はObj.toStringがproto.toStringと同じ引用かどうかを比較するだけでいいです.ソースのprop in objは判断が余分になったと思いますが、これはtrueに戻るとは限りませんか?理解の誤りがあれば、指摘してください.
    constructorを書き換えた場合、undersscoreはhasOwnPropertyで判断します.
    上記のいくつかの属性を書き換えた場合、undersscoreは確かにIE<9の中のボタンを取得できますが、一途な思いをしているビルさんも分かりません.constructorは本当に他の属性と区別して検査する必要がありますか?
    tostringという属性が書き換えられ、undersscoreの判断は非常に良く、書き換えられていないなら、対象のtoString方法は必ずプロトタイプチェーンに継承されています.対象のtoString方法がプロトタイプチェーンと一致しているかどうかを判断すればいいですが、hasOwnProptyで判定できますか?ビルの主人もいいと思います.hasOwnProperty方法は対象のkeyが自分の属性であるかどうか、すなわちプロトタイプチェーンから来ているかどうかを判断します.書き換えたらtrueに戻ります.そうでなければfalseに戻ります.
    書き換えられたconstructorはobjを使ってもいいですか?proto[prop]で判断しますか?もし書き換えられなかったら、Objc.stuctor==objc.com nstructor.prototype.com nstructorはtrueに戻ります.書き換えられたら、Object.prototype.com stuctor==Object.prototype.comはfalseに戻ります.
    この点に関しては、ビルの主も百思不得ですが、constructor属性と他の属性は明らかに区別されています.コードの理解から見れば、undersscoreという処理が受け入れやすいです.もしビルの主人の理解に出入りがあるならば、また指摘してもらいたいです.
    最後に、末尾に、for...inに対してIE<9下の互換性の問題、ビルの主な感じはそんなに重要ではありません.結局、誰がこれらの属性を書き換えることができますか?だから、このようなことがあると知っていればいいです.
    最後の最後に、この部分のソースコードの位置を提供します.興味のある学生は見てもいいです.https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L904-L 946