1. 程式人生 > 其它 >c++17 返回值優化

c++17 返回值優化

1、什麼是函式防抖和函式節流

    防抖(debounce)和節流(throttle)都是用來控制某個函式在一定時間內執行多少次的技巧,兩者相似不相同,基本思想都是某些程式碼不可以在沒有間斷的情況下連續重複執行

1.1 函式防抖

如果一個事件被頻繁執行多次,並且觸發的時間間隔過短,則防抖函式可以使得對應的事件處理函式,只執行最後觸發的一次。函式防抖可以把多個順序的呼叫合併成一次。

1.2 函式節流

如果一個事件被頻繁觸發多次,節流函式可以按照固定的頻率去執行相應的事件處理方法。函式節流保證一個事件一定事件內只能執行一次。

2、應用

  

 總的來說,函式防抖適合多次事件一次響應的情況,函式節流適合大量事件按照時間做平均分配觸發 

3、實現

  3.1 實現函式防抖

function debounce(fn, wait) {
  var timer = null;
    // 返回函式對debounce作用域形成閉包
  return function () {
      var context = this
      var args = arguments
      if (timer) {
          // 事件被觸發,清除timer並重新開始計時
          clearTimeout(timer);
          timer = null;
      }
      timer = setTimeout(function
() { fn.apply(context, args) }, wait) } } var fn = function () { console.log('boom') } setInterval(debounce(fn,500),1000) // 第一次在1500ms後觸發,之後每1000ms觸發一次 setInterval(debounce(fn,2000),1000) // 不會觸發一次(把函式防抖看出技能讀條,如果讀條沒完成就用技能,便會失敗而且重新讀條)

1、第一次呼叫函式的時候建立了一個定時器,在指定的時間之後執行程式碼

2、當第二次呼叫該函式的時候,會清除前一次的定時器並設定另一個

3、如果前一個定時器已經執行過了,這個操作就沒有任何意義

4、當前一個定時器沒有執行的時候,就是將他替換成一個新的定時器

5、目的是隻有在執行函式的請求停止了wait時間之後才執行 

3.2 實現函式節流

    1)利用時間戳實現 

// fn 是需要執行的函式
// wait 是時間間隔
const throttle = (fn, wait = 50) => {
  // 上一次執行 fn 的時間
  let previous = 0
  // 將 throttle 處理結果當作函式返回
  return function(...args) {
    // 獲取當前時間,轉換成時間戳,單位毫秒
    let now = +new Date()
    // 將當前時間和上一次執行函式的時間進行對比
    // 大於等待時間就把 previous 設定為當前時間並執行函式 fn
    if (now - previous > wait) {
      previous = now
      fn.apply(this, args)
    }
  }
}

// DEMO
// 執行 throttle 函式返回新函式
const betterFn = throttle(() => console.log('fn 函式執行了'), 1000)
// 每 10 毫秒執行一次 betterFn 函式,但是隻有時間差大於 1000 時才會執行 fn
setInterval(betterFn, 10)

 2) 利用定時器實現

function throttle(fn, threshold, scope) {
    let timer;
    return function () {
        let context = scope || this, args = arguments;
        if (!timer) {
            timer = setTimeout(function () {
                fn.apply(context, args);
                timer = null;
            }, threshold)
        }
    }
}

4、例項(scroll 事件)

     <!-- CSS樣式 -->
    <style>
        .wrap {
            width: 200px;
            height: 330px;
            margin: 50px;
            margin-top: 200px;
            position: relative;
            float: left;
        }

        .header {
            width: 100%;
            height: 30px;
            background-color: #a8d4f4;
            text-align: center;
            line-height: 30px;
        }

        .container {
            background-color: darkseagreen;
            box-sizing: content-box;
            width: 200px;
            height: 300px;
            overflow: scroll;
            position: relative;
        }

        .content {
            width: 140px;
            height: 800px;
            margin: auto;
            background-color: cadetblue;
        }
    </style>

<!-- html -->
<body>
    <div class="wrap">
        <div class="header">滾動事件:普通</div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header">滾動事件:<strong>加了函式防抖</strong></div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header">滾動事件:<strong>加了函式節流</strong></div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
</body>
 let els = document.getElementsByClassName('container');
        let count1 = 0,
            count2 = 0,
            count3 = 0;
        const THRESHOLD = 200;

        els[0].addEventListener('scroll', function handle() {
            console.log('普通滾動事件!count1=', ++count1);
        });
        els[1].addEventListener('scroll', debounce(function handle() {
            console.log('執行滾動事件!(函式防抖) count2=', ++count2);
        }, THRESHOLD));
        els[2].addEventListener('scroll', throttle(function handle() {
            console.log(Date.now(), ', 執行滾動事件!(函式節流) count3=', ++count3);
        }, THRESHOLD));

        // 函式防抖
        function debounce(fn, delay, scope) {
            let timer = null;
            let count = 1;
            return function () {
                let context = scope || this,
                    args = arguments;
                clearTimeout(timer);
                console.log(Date.now(), ", 觸發第", count++, "次滾動事件!");
                timer = setTimeout(function () {
                    fn.apply(context, args);
                    console.log(Date.now(), ", 可見只有當高頻事件停止,最後一次事件觸發的超時呼叫才能在delay時間後執行!");
                }, delay);
            }
        }

        // 函式節流
        function throttle(fn, threshold, scope) {
            let timer;
            let prev = Date.now();
            return function () {
                let context = scope || this,
                    args = arguments;
                let now = Date.now();
                if (now - prev > threshold) {
                    prev = now;
                    fn.apply(context, args);
                }
            }
        }

執行結果: