JavaScriptにおける関数再負荷(Function overloading)

6955 ワード

説明
JavaScriptには本当の意味での関数の再ロードがありません.
関数の再ロード
関数名は同じで、関数のパラメータリストは異なります.パラメータの数とパラメータの種類を含めて、パラメータによって異なる動作が実行されます.
例をあげてみましょう.
function overload(a){
    console.log('    ')
}

function overload(a,b){
    console.log('    ')
}

//            ,   java
overload(1);         //    
overload(1,2);    //    


//   JavaScript  
overload(1);         //    
overload(1,2);    //    
JavaScriptでは、同じスコープで、二つの名前のような関数が現れて、後は前のものをカバーします.だから、JavaScriptは本当の意味の重荷がありません.
しかし、様々な方法があります.JavaScriptの中でシミュレーションして重負荷の効果を実現できます.
まず第一の方法を見て、argmentsオブジェクトを通じて実現します.
アーグメンツオブジェクトは、関数を呼び出したときに関数に渡すすべてのパラメータが格納されている関数の内部のクラスのオブジェクトです.
function overload () {
  if (arguments.length === 1) {
    console.log('    ')
  }
  if (arguments.length === 2) {
    console.log('    ')
  }
}

overload(1);      //    
overload(1, 2);  //    
この例は非常に簡単であり、argmentsオブジェクトのlength属性を判断することによっていくつかのパラメータが決定され、どのような操作が行われるかを判断することである.
しかし、パラメータが少ない場合は幸いですが、パラメータが多いとif判定がたくさん必要になりますので、ご迷惑をおかけします.
だから、もう一つの古典的な例を見に行きます.この例を見る前に、まず一つの需要を見に来ます.私たちはusersオブジェクトがあります.usersオブジェクトのvalues属性に名前があります.一つの名前は二つの部分からなっています.左側はfirst-nameで、右側はlast-nameで、下のようになっています.
var users = {
  values: ["Dean Edwards", "Alex Russell", "Dean Tom"]
};
私たちはusersオブジェクトにfind方法を追加したいです.
任意のパラメータを送信しない場合は、users .values全体を返します.一つのパラメータを伝えると、first-nameとこのパラメータが一致する要素を返します.二つのパラメータを伝えると、first-nameとlast-nameが一致するように戻ります.
この需要の中でfind法はパラメータの個数によって異なる動作を実行する必要があります.次に私達は一つのaddMethod関数を通じて、usersオブジェクトにこのfind方法を追加します.
function addMethod (object, name, fn) {
  //      object[name]   ,   old 
  var old = object[name];

  //      object[name]   
  object[name] = function () {
    //                          ,     fn
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments);

      //      ,  old      ,
      //       old,         object[name]   
    } else if (typeof old === "function") {
      return old.apply(this, arguments);
    }
  }
}
addMethod関数は、3つのパラメータの最初の受信:結合方法のオブジェクト、2番目:結合方法の名前、3番目:バインディングが必要な方法
このaddMethod関数は、パラメータの個数を判断する際に、argmentsオブジェクトを使用するほか、関数のlength属性を使用した.
関数のlength属性は、関数定義時の参照の個数を返します.
簡単に関数のlengthは、関数にいくつかのパラメータが必要です.arguments.lengthは関数を呼び出した時、本当に関数にいくつかのパラメータを与えました.
function fn (a, b) {
  console.log(arguments.length)
}
console.log(fn.length);  // 2
fn('a');    // 1
私たちはこのaddMethod関数を使います.
//      ,    values  
function find0 () {
  return this.values;
}
//       ,  firstName       
function find1 (firstName) {
  var ret = [];
  for (var i = 0; i < this.values.length; i++) {
    if (this.values[i].indexOf(firstName) === 0) {
      ret.push(this.values[i
      ]);
    }
  }
  return ret;
}
//       ,  firstName lastName        
function find2 (firstName, lastName) {
  var ret = [];
  for (var i = 0; i < this.values.length; i++) {
    if (this.values[i
    ] === (firstName + " " + lastName)) {
      ret.push(this.values[i
      ]);
    }
  }
  return ret;
}
//   users                
addMethod(users, "find", find0);

//   users                
addMethod(users, "find", find1);

//   users                
addMethod(users, "find", find2);

//   :
console.log(users.find()); //["Dean Edwards", "Alex Russell", "Dean Tom"]
console.log(users.find("Dean")); //["Dean Edwards", "Dean Tom"]
console.log(users.find("Dean","Edwards")); //["Dean Edwards"]
addMethod関数は、クローズドの特性を利用して変数oldによって各関数を接続し、すべての関数をメモリに残します.
addMethod関数を呼び出すたびに、oldが生成され、クローズドが形成されます.私たちはconsole.dir(users.find)を通じて、find方法をコンソールに印刷してみてもいいです.
上記の例はjQueryの父John Resiggが書いたものです.彼は彼のブログと彼が書いた本「secrets of the JavaScript ninja」の第一版でも言及しました.本の中の第4章でFunction overloadingを説明しています.文の中のaddMethod関数は本の中の例4.15です.興味がある友達は見てください.
上記の例では、本質的にはパラメータの個数を判断し、個数に応じて異なる動作を実行しますが、以下に挙げた例はパラメータの種類を判断することによって、異なる動作を実行します.
jQueryのcssの方法を見てみます.
css()メソッドは、マッチする要素の1つまたは複数のスタイル属性を返したり、設定したりします.css(name|pro|[,val|fn])css()法を見ることができます.5つのパラメータの場合があります.3つは一つのパラメータで、もう2つは2つのパラメータです.一つのパラメータしかない場合は、パラメータタイプが文字列または配列で属性値を取得し、パラメータがオブジェクトであれば属性値を設定します.
jQueryのcss()メソッドは、パラメータの種類を判断して、どのような操作を行うかを決定することです.
jQuery 3.3.1のソースコードを見に来ました.
// name      
// value      
css: function( name, value ) {
    return access( this, function( elem, name, value ) {
        var styles, len,
            map = {},
            i = 0;

        //           
        //       ,  jQuery.css          ,    
        if ( Array.isArray( name ) ) {
            styles = getStyles( elem );
            len = name.length;

            for ( ; i < len; i++ ) {
                map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
            }

            return map;
        }

        //   value     undefined    jQuery.style       
        //   value    undefined    jQuery.css       
        return value !== undefined ?
            jQuery.style( elem, name, value ) :
            jQuery.css( elem, name );
    }, name, value, arguments.length > 1 );
}
css()方法は3つの方法に依存する:
1、jQuery.access()の方法は、この方法で一つ以上の属性値を取得または設定できます.
jQuery.accessの方法にはこのようなコードがあります.
//        
//      (key)     object,       
//           access()  ,             
if ( jQuery.type( key ) === "object" ) {
    chainable = true;
    for ( i in key ) {
        jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
    }

//      
} else if ( value !== undefined ) {
    ......
}
つまり、この方法では、最初のパラメータが文字列かオブジェクトかをcss()の方法で判断します.
2、jQuery.style()方法:DOMノードでスタイルの属性を読み込みまたは設定する
css()メソッドでは、2番目のパラメータ、つまり設定する属性値がある場合は、jQuery.style()メソッド設定スタイルを呼び出します.
3、jQuery.css():DOM元素でDOMスタイルの値を読み取ります.
ここのjQuery.cssはjQuery.extend( )によって追加された方法であり、最初に述べたcss()の方法はjQuery.fn.extend( )によって追加された方法であり、彼らは同じ方法ではない.
jQuery.exted()とjQuery.fn.exted()の違い
jQuery.exted()はjQuery類のためにクラスを追加する方法(静的方法)であり、jQuery類を通じて(直接に$xxx呼び出しを使う).
jQuery.fn.exted()はjQuery類のためにメンバー数を追加する(例の方法)、すべてのjQueryのインスタンスは直接に呼び出すことができます.
積載のメリット
重荷重は、複数の機能が似ている関数を一つの関数に統合して、関数名を繰り返し利用します.jQueryの中のcss()の方法が重載を使わないと、5つの異なる関数が必要になります.機能を完成するには、5つの異なる関数名を覚えなければなりません.各関数に対応するパラメータの個数とタイプを覚えなければなりません.明らかに面倒くさいです.
締め括りをつける
JavaScriptは本当の意味では重載されていませんが、重負荷の効果はJavaScriptではよく見られます.たとえば配列のsplice()方法は一つのパラメータを削除できます.二つのパラメータは一部を削除できます.三つのパラメータは削除されて、また新しい要素を追加できます.また、たとえば、パーrseInt()方法では、一つのパラメータが入ってきたら、十六進法で解析するか、十進法で解析するかを判断します.二つのパラメータが入ってきたら、二つ目のパラメータを数字の基数として解析します.
本文で述べたように、重荷重効果を実現する方法は、本質的にはパラメータを判断し、パラメータの個数を判断するか、パラメータの種類を判断するかにかかわらず、パラメータによってどのような操作を行うかを決定します.
重い荷物は私たちに多くの便利をもたらしますが、悪用もできません.まったく関係のない関数を一つの関数にしないでください.
参照
JavaScript関数の再負荷について説明します.
jsはどのように重積載を実現しますか?
JavaScript関数の再ロード