函数式编程与闭包(2)

在js中函数就是一个普通的对象(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们可以在程序运行的时候通过new Function(‘alert(1)’)来构造一个新的函数。

  • 把函数赋值给变量

// 把函数赋值给变量

let fn = function(){

    console.log('hello world')

};

fn();



// 一个示例

const BlogController = {

    index (posts) { return Views.index(posts) },

    show (post) { return Views.show(post) },

    create (attrs) { return Db.create(attrs) },

    update (post, attrs) { return Db.update(post, attrs) },

    destroy (post) { return Db.destroy(post) },

}



// 如果我们将来遇到一个函数包裹一个函数,而且它的形式也相同时,我们可以认为,这是两个一样的函数,那我们就可以把这段代码进行一点精简,我们可以看到index和其内部的Views.index是一样的,所以我们可以把Views.index赋值给index,注意,我们是将一个方法或者函数赋值给另一个方法,不是把函数的调用赋值给另一个方法



// 当我们改造完成后,代码量将减少很多,功能也完全一样,这里我们就用到了将一个函数或者方法赋值给另一个函数或者方法



// 优化

const BlogController = {

    index: Views.index,

    show: Views.show,

    create: Db.create,

    update: Db.update,

    destroy: Db.destroy

}



  • 函数式一等公民是我们后面要学习的高阶函数、柯里化的基础

高阶函数


什么是高阶函数

  • 高阶函数(Higher-order function) — 学过react的话会觉得名字和其中的高阶组件一样,其实react的高阶组件本质上就是高阶函数

    • 可以把函数作为参数传递给另一个函数

    • 可以把函数作为另一个函数的返回结果

  • 函数作为参数

    
    // 高阶函数---函数作为参数
    
    
    
    // forEach
    
    function forEach (array,fn){
    
        for(let i = 0; i < array.length; i++){
    
            fn(array[i])
    
        }
    
    };
    
    
    
    // filter
    
    function filter (array,fn){
    
        let results = [];
    
        for(let i = 0; i < array.length; i++){
    
            if(fn(array[i])){
    
                results.push(array[i])
    
            }
    
        }
    
        return results;
    
    };
    
    
    
    
  • 函数作为参数的好处

    • 可以使我们的函数更灵活,调用forEach不需要考虑函数内部是如何实现的,该函数把内部实现的细节帮我们屏蔽了,而且名字都是符合见名知意的,比如forEach一看就是遍历的,filter一看就是过滤的
  • 函数作为返回值


// 高阶函数---函数作为返回值

function fn(){

    let msg = 'hello world';

    return function (){

        console.log(msg);

    };

};



// 调用方式一

let func = fn();

func();



// 调用方式二

fn()();



// 实际案例:只执行一次的函数

function once(fn){

    let done = true;

    return function(){

        if(done){

            done = false;

            return fn.apply(this,arguments);

            // this --- 将自身this传递过去 --- 不写就是undefind

            // arguments --- 将接受的参数传递过去 --- 不写就是undefind

        };

    };

};



let on = once(function(x){

    console.log(`执行了${x}次`);

});



使用高阶函数的意义

===================================================================

对运算过程进行抽象,也就是把运算过程抽象成函数,然后在任何地方都可以去重用这些函数

  • 抽象可以帮我们屏蔽细节,只需要关注我们的目标

  • 高阶函数是用来抽象通用的问题

  • 示例


//遍历一个数组



//面相过程的方式

let array = [1,2,3,4]

for(let i = 0; i < array.lenth; i++){

    console.log(array[i])

}





//高阶函数

let array = [1,2,3,4]



forEach(array, item=>{

    console.log(item)

})



let r = filter(array,item => {

    return item % 2 === 0 

})



  • 意义

    • 可以使函数更加灵活

    • 抽象可以帮助我们屏蔽细节

常用高阶函数

================================================================

  • forEach

  • filter

  • map

  • every

  • some

  • find / findIndex

  • reduce

  • sort

我们之前已经模拟过forEachfilter,所以我们现在来模拟mapeverysome


// map --- 数组中的一个方法,对数组中的每一个元素进行遍历,并对每一个元素进行一个处理,并对处理后的结果存储到一个新数组中然后返回

const map = (array,fn) => {

    let results = [];

    for(let value of array){

        results.push(fn(value));

    }

    return results

};

let arr = [1,2,3,4];

arr = map(arr,v => v * v );

console.log(arr);



// every --- 遍历数组中的每一个元素,并对其做一个判断,其中有一个是false,其返回值就是false

const every = (array, fn) => {

    let results = true;

    for(let item of array){

        results = fn(item);

        if(!results){

            break

        }

    };

    return results;

};



let arr = [1,2,3,4];

let a = every(arr,v => v > 0);

console.log(a);



// some --- 遍历数组中的没一个元素,并对其做一个判断,其中有一个是true,其返回值就是true

const some = (array,fn) => {

    let results = false;

    for(let item of array){

        results = fn(item);

        if(results){

            break;

        };

    };

    return results;

};



let arr = [1,2,3,4];

let a = some(arr,v => v % 2 === 0);

console.log(a);



  • 这三个方法都可以去接收一个函数,他们都是高阶函数,通过把一个函数传递给另一个函数,我们可以让这个函数变得更灵活

闭包

============================================================

  • 闭包(Closure):函数和其周围的状态(词法环境)的引用捆绑在一起形成闭包。

    • 可以在另一个作用域中调用一个函数的内部函数并访问到该函数的作用域中的成员
  • 其实闭包就是一个可以获取到其他函数内部变量的函数,他必须要满足三个条件才能被称之为闭包

    • 首先要有一个函数

    • 然后在这个函数内部去嵌套另一个函数

    • 最后需要内层函数去访问到外部函数的变量

  • 示例


function fn(){

    let msg = 'hello world';

    return function (){

        console.log(msg);

    };

};

let func = fn();

func();





function once(fn){

    let done = true;
#  最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/bab6c6b892d461edb8d55e31ed6b2ddc.jpeg)

![](https://img-blog.csdnimg.cn/img_convert/32641ae325c14791996287c968efbf24.png)

![](https://img-blog.csdnimg.cn/img_convert/673364b569bf8d44849e09870825907e.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618191877)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**
*

**因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中...(img-vxIpG6SP-1715834663935)]

[外链图片转存中...(img-xajIMYDL-1715834663936)]

[外链图片转存中...(img-X32HdM0b-1715834663936)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618191877)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值