首先我們需要知道什麼是高階函式
- 函式作為引數傳遞
- 函式作為返回值輸出
滿足以上一個條件就可以稱之為高階級函式
函式作為引數傳遞
看一下例子
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變成一個全域性變數不行嗎?可以的。為啥不這樣做你自己去想吧。知道了答案請留言。謝謝。
我們的高階函式有很多玩法,比如柯理化和反柯理化。學無止境啊。