自分のアンダースコアシリーズを作る(一)

6961 ワード

undersscoreは開発においてよく使われるjavascriptツールライブラリとして、豊富な関数式プログラミング機能を提供しています.このライブラリはオリジナルのjavascript元のオブジェクトを開拓していません.代わりに、カスタム_オブジェクトに100以上の方法関数を提供しています.このシリーズでは、ソースの観点から、自分のundersscoreフレームを作成します.
一、フレーム設計
1.1自己実行関数
現代のjsライブラリのフレームデザインは、一般的には自己実行関数としての形で、自己実行関数は一般的に2つの形があります.
(function(){
    //    
}())
(function(){
    //    
})()
関数宣言の形式はwindowオブジェクトにマウントされますが、関数表現の形式はwindowオブジェクトに属性として存在します.これは変数汚染を引き起こします.自己実行関数の利点は変数の汚染を防ぐことができます.関数が実行されたらすぐに破棄されます.
1.2使用スタイル
underscoreには2つのスタイルがあります.一つはオブジェクト指向タイプ、もう一つは関数タイプです.
//   
_.map([1, 2, 3], function(n){ return n * 2; });
_([1, 2, 3]).map(function(n){ return n * 2; });
したがって、アンダースコアクラスを定義するには、オブジェクトと関数の2つのシーンを考慮する必要があります.関数として呼び出すときは_を必要とします.構造関数として彼の実用化を返します.コードは以下の通りです
(function(root){
    var _ = function (obj) {
        if (!(this instanceof _)) {
          return new _(obj)
        }
    }
    root._ = _
}(this))
1.3使用環境
今、フロントエンドの開発はモジュール化を重視しています.Nodeのサービスで言えば、commmonjs規格があります.クライアントで言えば、AMDとCMD規格があります.対応するモジュール搭載器はrequirejsとseajsです.現在通行しているjavascriptモジュールの仕様は主にcomonjsとAMDに集中していますので、定義されたunderscor e庫を様々な仕様に適用できるようにします.フレームの定義には使用環境を検出し、各種仕様に対応する必要があります.
  • サービス端末:comonjs規範、module.exportが存在するかどうかを検出し、満足する時module.export={}を通じてundersscoreを暴露し、満足しない場合はwindowオブジェクトを通じて暴露します.
  • クライアント:AMD仕様で、define.amdが存在するかどうかを検出し、満足する場合はdefine('**', [], function(){ return '***' })を通じてモジュール
  • を露出する.
    (function (root) {
      var _ = function (obj) {
        if (!(this instanceof _)) {
          return new _(obj)
        }
      }
      // commonjs       module.exports     
      if ((typeof module !== 'undefined' && module.exports)) {
        module.exports = {
          _: _
        }
      } else {
        root._ = _;// window       
      }
      // amd   ,   define.amd     
      if (typeof define == 'function' && define.amd) {
        define('underscore', [], function () {
          return _;
        });
      }
    
    }(this))
    
    1.3.1業務上の使用
    // commonjs
    const _ = require('./underscore.js')
    console.log(_)
    
    1.3.2クライアント使用
    // AMD
    require(['underscore'], function (underscore) {
      console.log(underscore)
    })
    
    1.4方法の定義
    undersscoreの呼び出しは、_.unique()を通してもいいし、_().unique()を通してもいいです.二つの方法の効果は同じですが、フレーム設計時に二つの方法を定義する必要があります.オブジェクトの静的な方法、もう一つは拡張_です.オブジェクトプロトタイプチェーン上の方法.
    _.uniqe = function() {}
    
    _.prototype.unique = function() {}
    
    冗長コードを回避するために、定義された静的方法をモデルチェーン上の方法としてコピーすることができます.
    (function(root){
        ···
        _.mixins = function() {
            //           
        }
        _.mixins() //     
    }(this))
    
    
    mixins法の実現には、undersscoreオブジェクト上のすべての静的方法を遍歴する必要があるので、まずはエルゴード法を完成する必要がある.eachの実現
    1.41_.each
    _.each(list,iteratee,context)Alias:forEachはlistのすべての要素を遍歴して、順番に各要素をパラメータとしてiteratee関数を呼び出します.contextパラメータを渡すと、iterateeをcontextオブジェクトにバインドします.iterateeを呼び出すたびに3つのパラメータが渡されます.リストがJavaScriptオブジェクトである場合、iterateeのパラメータは(value、key、list)です.リストを返します.
    eachの最初のパラメータは、ドキュメントによって行列、クラス行列、オブジェクトの3種類、配列とオブジェクトのエルゴード時の処理方法が異なります.前者のコールバック関数は値とアンダースケール、後者の処理は値と属性です.
    //     ,     
    (function(root) {
        ···
        _.each = function (list, callback, context) {
            // context      callback  this    
            var i = 0;
            var key;
            if (isArrayLikeLike(list)) { //    ,   
              for (var i = 0; i < list.length; i++) {
                context ? callback.call(context, list[i], i, list) : callback(list[i], i, list)
              }
            } else { //   
              for (key in list) {
                context ? callback.call(context, list[key], key) : callback(list[key], key)
              }
            }
          }
        var isArrayLike = function (collection) {
            //      collection   length    
            var length = collection.length;
        
            // length   ,  ,     MAX_ARRAY_INDEX
            // MAX_ARRAY_INDEX = Math.pow(2, 53) - 1
            return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
        }
    }(this))
    
    
    
    1.4.2_.mixin
    mixin方法の設計は、underscoreプロトタイプオブジェクト上でより多くの方法を拡張することを目的としており、これはユーザー独自の方法、例えば
    _.mixin({
      capitalize: function(string) {
        return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
      }
    });
    _("fabio").capitalize();
    => "Fabio"
    
    もちろん、静的方法をプロトタイプチェーンに内部コピーする方法にも使用されうる.
    (function(root){
        ···
        var push = Array.prototype.push
        var _ = function (obj) {
            if (!(this instanceof _)) {
              return new _(obj)
            }
            this.wrap = obj //             
          }
        _.mixins = function (obj) {
            _.each(obj, function (value, key) {
              _.prototype[key] = function () {
                var args = [this.wrap]
                push.apply(args, arguments)
                return value.apply(this, args)
              }
            })
          }
      _.mixins(_)
    }(this))
    
    注目点は、argmentsの処理において、静的方法は、方法のパラメータである_.unique( , )を伝達する必要があり、方法の一例としてのターゲットソースは、構造オブジェクトの属性である_( ).unique( )に記憶されているので、例示的な方法を定義するには、結合属性とコールバック関数が必要である.すなわちArray.prorotype.push.apply([this.wrap], arguments)は、パラメータとして静的方法に渡され、処理結果に戻る.
    クラスの配列を行列に変換する方法
  • Array.prototype.slice.call( )
  • var a = []; Array.prototype.push.apply(a, ); console.log(a);
  • var a = []; Array.prototype.concat.apply(a, ); console.log(a);
  • ES 6方法Array.from( )
  • ES 6拡張演算子var args = [... ]
  • 1.5チェーン呼び出し
    1.5.1_.chain()
    パッケージのオブジェクトを返します.パッケージのオブジェクトに呼び出す方法は、パッケージのオブジェクト自体に戻ります.
    undersscoreでのメソッドの呼び出しは、処理後の値を返しますので、メソッドのチェーン呼び出しをサポートすることはできません.チェーンコールが必要であれば、chain()方法を使用する必要があり、chainの使用は、メソッドを呼び出すたびにundersscoreの例示的なオブジェクトに戻り、valueメソッドを呼び出してからリターンを停止する.
    (function(root){
        ···
        // chain      _   ,                
        _.chain = function(obj) {
            var instance = _(obj);
            instance.chain = true; 
            return instance
          }
        //              ,    ,      ,          ,
        var chainResult = function (instance, obj) {
            return instance.chain ? _(obj).chain() : obj
          }
        _.mixins = function (obj) {
            _.each(obj, function (value, key) {
              _.prototype[key] = function () {
                var args = [this.wrap]
                push.apply(args, arguments)
                return chainResult(this, value.apply(this, args)) //           ,     chainResult   ,  chainResult          
              }
            })
          }
    }(this))
    
    1.5.2 value()
    チェーン呼び出しは、undersscoreの方法を彼の例示的なオブジェクトに戻すため、この呼び出し動作を終了する必要がある場合は、value()を使用する必要があります.value()メソッドは呼び出しの結果を返します.
    (function(root){
        ···
        _.value = function(instance) {
            return instance.wrap
        }
    }(this))
    
    未完次号.
    本文は博主のオリジナル文章です.転載は出典を明記してください.https://www.cnblogs.com/kidflash/p/10077643.html