javaScript高階級函式

Link-X發表於2018-12-10

首先我們需要知道什麼是高階函式

  • 函式作為引數傳遞
  • 函式作為返回值輸出

滿足以上一個條件就可以稱之為高階級函式

函式作為引數傳遞

看一下例子

function iterator () {
     const obj = {
        message: '123'
        status: false
    }
    obj.status = true
    return obj
}
const obj2 = iterator()
console.log(obj2) // { message: '123', status: true }
複製程式碼

沒毛病,but 問題來了,產品經理走過來和你提了一個需求,我們要在iterator 外面做一些事情,這個事情做完之後再判斷obj.status是要等於true還是false。emmmmmm

好既然產品經理都這麼說了。那我們就開幹吧。

function iterator (cb) {
     const obj = {
        message: '123'
        status: false
    }
    cb(obj)
    return obj
}
const obj2 = iterator((obj) => {
    console.log(obj2) // { message: '123', status: false }
    if (true) {
        obj.status = true
    } else {
        obj.status = false
    }
})
console.log(obj2) // { message: '123', status: true }
複製程式碼

???? 完成了一個產品經理的需求。函式當值傳遞,這是一個高階函式
其實我們平時寫的dom事件就是這樣子方式,通過傳入一個回撥函式。

$('#btn').on('click', function() {
    $('#massage').show();
});
複製程式碼

傳入了一個函式,當click監聽到了資訊,就會執行你傳入的函式。
讓我們來個稍微高階點的。

觀察者模式

class observer {
    constructor() {
        // 用來儲存所有的事件
        this.obj = {}
    }
    emit (str) {
        // 釋出一個事件
        const params = Array.prototype.slice.call(arguments, 1)
        this.obj[str] = (cb) => {
            cb(...params)
        }
    }
    on (str, fn) {
        // 執行一個事件
        this.obj[str](fn)
    }
}

const ob = new observer()
ob.emit('click', 1234, 'abcd')
ob.on('click', (a,b) => { 
    console.log(a,b) // 1234, 'abcd'
})
複製程式碼

沒毛病,雖然這個程式碼缺乏嚴謹,but 我們只是為了展示一下搞基函式的方式之一函式當引數傳遞。

函式作為返回值輸出

    function func () {
        let a = 1
        return function () {
            return a++
        }
    }
    let bb = func()
    cosnole.log(bb())
    cosnole.log(bb())
    cosnole.log(bb())
    cosnole.log(bb())
複製程式碼

相信大家對這個會列印啥都不陌生吧。

//1 2 3 4
複製程式碼

每個函式都是一個閉包,js訪問一個變數是,會從自身作用域開始查詢再慢慢向上查詢,找到的第一個就取值。func這個函式 return 的這個function 沒有a這個變數,所以就報錯?no 但是它父親有啊。它會向上找到後執行操作。最後外面js又發現全域性變數bb引用了 這個function。所以js的自動垃圾回收機制放了這個a變數一馬,沒有回收它.

so 我們再來個稍微高階點的。

節流

function debounce(fn, time) {
  // 記錄當前執行函式狀態
    let timer = null;
    let context = this;
    let args = arguments;
     return function() {
        if (timer) {
            // 任你滑,多執行一次算我輸
            return false
        }
        timer = setTimeout(function() {
          clearTimeout(timer);
          timer = null
          fn.apply(context, args);
        }, time || 500);
      }
}
function foo() {
  console.log('你過來啊');
}

// 過 2 秒觸發一次
window.addEventListener('scroll', debounce(foo, 2000));
複製程式碼

這是一個簡單的節流函式,作用就是節流。臥槽這麼粗暴的嗎? 是的,我們們是一篇講解搞基函式的文章,說什麼節流。要什麼手錶.
通過返回一個函式,我們實現了,一個簡單的節流函式。這是有同學問,為啥那麼複雜,我們直接把timer變成一個全域性變數不行嗎?可以的。為啥不這樣做你自己去想吧。知道了答案請留言。謝謝。

我們的高階函式有很多玩法,比如柯理化和反柯理化。學無止境啊。

相關文章