underscore関数がドド迫力を実現します.

14159 ワード

前の文 JavaScriptにおける関数節流と関数の振動除去の概念と応用シーンについて簡単な理解を行いました.本稿では、関数による手ぶれの実現を深く探究します.(関数が分かりませんので、概念を振ってください.前文を見てください. JavaScript関数の節流と関数はシーンを震えて分析します. )
私達はscrollイベントを例にとって、どのように一回のウィンドウを転がして一つの印刷を実現するかを探究します. ハローワールド 文字列
それを節流しない場合、または手振れ制御を行います.
window.onscroll = function() {
  console.log('hello world');
};
このように一回スクロールすると、実際にN個以上印刷されます. hello world.関数の後ろの基本的な考えとしては、コードの一部は、中断なしで連続して実行できないことがあります.最初の関数を呼び出して、指定された時間間隔の後にコードを実行します.2回目の呼び出しで、前回のタイマーをクリアして、他のタイマーを設定します.前のタイマーがすでに実行されていたら、この操作には意味がありません.しかし、前のタイマーがまだ実行されていない場合は、新しいタイマーに置き換えられます.目的は、実行関数の要求が一時停止された後だけ実行されます.
「高程三」は最も簡潔で古典的な手ぶれコードを提供しています.
function debounce(method, context) {
  clearTimeout(method.tId);
  method.tId = setTimeout(function() {
    method.call(context);
  }, 1000);
}

function print() {
  console.log('hello world');
}

window.onscroll = function() {
  debounce(print);
};
ウィンドウ内を一度スクロールして停止し、1000 ms後に印刷しました. ハローワールドは1000 msの遅延タイマーを設置していますので、細かい考えがとても巧妙です.
undersscoreはその基礎の上で拡充して、直接コードを見て、大量の注釈を含みます.
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
//     (              )
// sample 1: _.debounce(function(){}, 1000)
//          1000ms    
// sample 1: _.debounce(function(){}, 1000, true)
//            (          )
_.debounce = function(func, wait, immediate) {
  var timeout, args, context, timestamp, result;

  var later = function() {
    //          later        ,                  
    //       wait(       wait),     
    var last = _.now() - timestamp;

    //      last   [0, wait)  
    //        ,        
    // last         0  ?
    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      //           
      timeout = null;
      //      
      //             
      //          (callNow),         
      //        timeout     ,              
      //         ,     func   
      if (!immediate) {
        //    func   
        result = func.apply(context, args);
        //     timeout     null   
        //          
        if (!timeout)
          context = args = null;
      }
    }
  };

  //  ,       ,        
  return function() {
    //      this   
    context = this;
    args = arguments;

    //       ,     
    // later      last        
    //                  wait seconds  
    //                 wait seconds          
    timestamp = _.now();

    //             
    // immediate     true,   timeout     
    // immediate     true       
    //      !timeout    ,      ,       
    //               timeout,     timeout                
    var callNow = immediate && !timeout;

    //    wait seconds     later   
    //      callNow(    callNow,    later   ,  later                )
    //           ,              if    
    if (!timeout)
      //     timeout,           if    
      timeout = setTimeout(later, wait);

    //        
    if (callNow) {
      // func         
      result = func.apply(context, args);
      //     
      context = args = null;
    }

    return result;
  };
};
ちょっと待ってください.コードがこんなに多くなりました.基礎版よりどのような機能が多くなりましたか?
まず、基礎版ができます.私達も同じようにできます.連続スクロール後に停止した1000 ms後に印刷します. ハローワールド:
function print() {
  console.log('hello world');
}

window.onscroll = _.debounce(print, 1000);
連続スクロールが終了した後ではなく、スクロールがトリガされた時に文字列を印刷することもできます.3番目のパラメータに入ると、自動的に2番目のパラメータを無視します.
function print() {
  console.log('hello world');
}

window.onscroll = _.debounce(print, 1000, true);
このように連続スクロールに対しても一回だけ印刷されますが、イベントの最初のトリガの時です.
コールバック関数はパラメータが必要ですか?問題はありません.
function print(a) {
  console.log('The passed item is: ' + a);
}

var callback = _.debounce(print, 1000);
window.onscroll = function() {
  var item = 'zichi';
  callback(item);
};
もちろん、機能の優位性以外にも、性能も多く向上しています.最も明白なのは基礎版の各トリガイベントはタイマーをキャンセルして、タイマーを再設定します.一方、undersscoreでは一定時間後にタイマーをキャンセルして、タイマーを再設定します.他の多くはソースを詳しく調べられます. jashkenas/undersscore啱1269)