高阶函数

用代码解释代码,用函数证明函数

基本概念


高阶函数主要指:

  • 这个函数中的参数是函数
  • 这个函数的返回值是函数

before函数(装饰函数,AOP)


在执行一个函数之前去执行另一个函数

const f1 = ()=>{
    console.log("正在执行任务...")
}

// 要在f1之前打印 开始... 
Function.prototype.before = function(beforeFn){   // beforeFn叫回调函数
    // 箭头函数中没有this
    return ()=>{
        beforeFn();
        this(); // 谁调用了before函数,this就指谁
    }
}
// f2是返回的新函数
const f2 = f1.before(()=>{
    console.log("开始...")
})
f2()

高阶传参

const f1 = (...args)=>{
    console.log("正在执行任务...",args)
}
Function.prototype.before = function(beforeFn){   // beforeFn叫回调函数
    return (...args)=>{  // ...args 叫rest参数 用来接收1,2,3
        beforeFn();
        this(...args);  // 把1,2,3继续传递给f1
    }
}
const f2 = f1.before(()=>{
    console.log("开始...")
})
f2(1,2,3)

包括函数


包括函数:在执行某个函数之前执行若干个函数,在执行某个函数之后执行若干个函数,事务函数

把之前的函数存起来,把之后的函数存起来,就把它存储到对象

let f1 = function(){
    console.log("正在执行任务...")
}
let wrappers = [
    {
        // warpper
        init(){
            console.log("hello 1")
        },
        close(){
            console.log("bye 1")
        }
    },
    {
        // warpper
        init(){
            console.log("hello 2")
        },
        close(){
            console.log("bye 2")
        }
    }
]
// 定义一个函数,把上面两者结合起来
const work = (core,wrappers)=>{
    // core是核心函数
    wrappers.forEach(wrap=>{
        wrap.init()
    })
    core()
    wrappers.forEach(wrap=>{
        wrap.close()
    })
}
work(f1,wrappers)

让人想起的了函数柯里化

curring又称部分求值。一个curring的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数中被真正的需要求值的时候,之前传入的所有参数被一次性用于求值。

after函数


调用一个函数n次后,触发另一个函数,用after函数实现

const after = (times,fn)=>{
    return ()=>{
        if(--times === 0){
            fn()
        }
    }
}
const f1 = after(3,()=>{
    console.log("调用3次后才执行...")
})
f1()
f1()
f1()

多次调用才执行
我又想到了函数节流。。。。
在一定的时间内,函数只触发一次,能大大降低了频率问题

function throttle(fn, wait) {
    let last = 0
    return () => {
        var now = +new Date().getMilliseconds();
        if (now - last > wait) {
            fn()
            // console.log(now-last)
            last = now;
        } else {
            // console.log(now-last)
            console.log("什么情况")
        }
    }
}
const f3 = throttle(() => {
    console.log('ZZZZ.....')
}, 500);
f3()

all函数


const fs = require("fs")
let content = {};
let index = 0;
fs.readFile("name.txt","utf8",(err,data)=>{
    content['name'] = data
    index++;
    out()
})
fs.readFile("age.txt","utf8",(err,data)=>{
    content['age'] = data
    index++;
    out()
})
function out(){
    if(index == 2){
        console.log(content)
    }
}
const fs = require("fs")
let content = {};
const after = (times,fn)=>{
    return ()=>{
        if(--times === 0){
            fn()
        }
    }
}
let newAfter = after(2,()=>{
    console.log(content)
})
fs.readFile("./name.txt","utf8",(err,data)=>{
    content['name'] = data
    newAfter()
})
fs.readFile("./age.txt","utf8",(err,data)=>{
    content['age'] = data
    newAfter()
})
// 两者都成功才输出结果

emmmm…这让人想起了函数分时。。。。真的(〃‘▽’〃)

和节流函数的应用场景不同,当短时间内接受的数据过多过大,可能会有影响效率等问题,特别是如果我们需要在短时间内才页面中插入大量的DOM节点,那显然会让浏览器吃不消,这可能会引起浏览器的假死,所以我们需要进行分时函数,分批插入。

// 分时函数
var timeChunk = function (ary, fn, count) {
    var timer;

    var start = function () {
        for (var i = 0; i < Math.min(count || 1, ary.length); i++) {
            fn && fn(ary.shift())
        }
    };

    return function () {
        timer = setInterval(function () {
            if (ary.length === 0) { // 如果全部节点都已经被创建好
                return clearInterval(timer);
            }
            start();
        }, 200); // 分批执行的时间间隔,也可以用参数的形式传入
    };
};

var ary = [];
for (var i = 1; i <= 1000; i++) {
    ary.push(i);
};
var renderFriendList = timeChunk(ary, function (item) {
    console.log(item)
}, 8);
renderFriendList();

发布订阅


一种概念,订阅时把函数保存到一个容器中,发布时拿到这个容器并把里面的函数一一执行

订阅和发布之间没有关系

const fs = require("fs")
let content = {};
let e = {  //订阅
    arr:[],
    on(fn){
        this.arr.push(fn)
    },
    emit(){
        this.arr.forEach(fn=>fn())
    }
}

e.on(()=>{
    // console.log("订阅了... ")
    if(Object.keys(content).length === 2){
        console.log(content)
    }
})

e.emit()  // 发布
fs.readFile("name.txt","utf8",(err,data)=>{
    content["name"] = data;
    e.emit()  // 发布
})
fs.readFile("age.txt","utf8",(err,data)=>{
    content["age"] = data;
    e.emit()  // 发布
})

同样的,既然可以保存函数到最后一起执行,又怎么可能不能保存多个呢

let e = {
    arr:[],
    on(fn){
       this.arr.push(fn)
    },
    emit(){
        this.arr.forEach(fn=>fn())
    }
}
e.on(()=>{
    console.log("哈哈1")
})
e.on(()=>{
    console.log("哈哈2")
})
e.on(()=>{
    console.log("哈哈3")
})
e.emit()

观察者模式


观察者模式分为观察者和被观察者(在被观察者中存储观察者),观察者模式是基于订阅和发布,但二者之间有关系

// 被观察者
class Subject{
    constructor(){
        this.arr = [] // 存储谁在观察者
        this.state = "很开心"
    }
    attach(o){
        this.arr.push(o)
    }
    setState(newState){
        this.state = newState
        this.arr.forEach(o=>o.update(newState))
    }
}
// 观察者
class Observer{
    constructor(name){
        this.name = name;
    }
    update(newState){
        console.log(this.name,"小宝宝状态:",newState)
    }
}
let s = new Subject("小宝宝")
let o1 = new Observer("我")
let o2 = new Observer("我媳妇")
s.attach(o1)        //  我 小宝宝状态: 不开心
s.attach(o2)        //  我媳妇 小宝宝状态: 不开心
s.setState("不开心") 
// console.log(s.state)

一点cones


惰性加载函数

有两种实现惰性载入的方式,第一种事函数在第一次调用时,对函数本身进行二次处理,该函数会被覆盖为符合分支条件的函数,这样对原函数的调用就不用再经过执行的分支了,我们可以用下面的方式使用惰性载入重写addEvent()。

function addEvent (type, element, fun) {
    if (element.addEventListener) {
        addEvent = function (type, element, fun) {
            element.addEventListener(type, fun, false);
        }
    }    else if(element.attachEvent){
        addEvent = function (type, element, fun) {
            element.attachEvent('on' + type, fun);
        }
    }    else{
        addEvent = function (type, element, fun) {
            element['on' + type] = fun;
        }
    }   
     return addEvent(type, element, fun);
    }

在这个惰性载入的addEvent()中,if语句的每个分支都会为addEvent变量赋值,有效覆盖了原函数。最后一步便是调用了新赋函数。下一次调用addEvent()的时候,便会直接调用新赋值的函数,这样就不用再执行if语句了。

第二种实现惰性载入的方式是在声明函数时就指定适当的函数。这样在第一次调用函数时就不会损失性能了,只在代码加载时会损失一点性能。一下就是按照这一思路重写的addEvent()。

var addEvent = (function () {  
    if (document.addEventListener) {  
        return function (type, element, fun) {
            element.addEventListener(type, fun, false);
        }
    }  
   else if (document.attachEvent) {  
          return function (type, element, fun) {
            element.attachEvent('on' + type, fun);
        }
    }  
      else {        
         return function (type, element, fun) {
            element['on' + type] = fun;
        }
    }
})();

请参考javascript之惰性函数

This`s all,thanks!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
大学生在线租房平台管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、报修评价管理、字典管理、房东管理、房屋管理、房屋收藏管理、房屋留言管理、房屋租赁管理、租房论坛管理、公告信息管理、留言板管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生在线租房平台管理系统可以提高大学生在线租房平台信息管理问题的解决效率,优化大学生在线租房平台信息处理流程,保证大学生在线租房平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理大学生在线租房平台信息,包括房屋管理,培训管理,报修管理,薪资管理等,可以管理公告。 房屋管理界面,管理员在房屋管理界面中可以对界面中显示,可以对房屋信息的房屋状态进行查看,可以添加新的房屋信息等。报修管理界面,管理员在报修管理界面中查看报修种类信息,报修描述信息,新增报修信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
基于hal库的OLED显示屏驱动C语言实现源码.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值