JavaScript中的“函数式编程”

前言

我们虽然之前老是听说过“函数式编程”,但一直不能理解,我们静下心来研究了一下,才发现这些东西真的很巧妙。

在React这些框架中,对象,函数为王,因为框架已经帮你打建好了

在框架中,数据为王,那些函数本身就是用来处理数据

这里我们要用更高层的思维,而放弃底层思维,这些本身都是用户数据,前段传递到后端,后端传递到前段

我们用固定的编写好的函数来处理数据返回数据,或者把函数传递到框架(函数),这思想要有。

甚至函数返回函数,为什么呢,因为一个函数也可以看做一个变量,直接把函数作为一个工具传递到另外一个函数中使用

 

一、不可变性

一个对象Object Person,当被创建出来之后,就不能被修改原件了,要修改,只能拷贝一份新的。

同理,数组也是一样的,我们要拷贝一份新的,所有的操作都在拷贝件上来进行。

函数式编程,函数为王,一切基于函数,这些转换基本都是在函数中发生的。

此时,你就理解“展开运算符”的作用了,如下面这个,我们直接创建了一个makeBackpackingMeals函数来帮助我们构造

makeBackpackingMeals是一个标准的纯函数,单纯用于数据转换,把它看做处理数据的工具,一切以数据为核心!! 

复制代码
    const morning = {
        breakfast: "oatmeal",
        lunch: "peanut butter and jelly"
    };

    const dinner = "mac and cheese";

    makeBackpackingMeals = (morningFood, dinnerFood)=>{
        return {
            ...morningFood,
            dinnerFood
        }
    }

    packingMeals =  makeBackpackingMeals(morning, dinner)

    console.log(packingMeals);
    // {
    //     breakfast: "oatmeal",
    //     lunch: "peanut butter and jelly",
    //     dinner: "mac and cheese"
    // }
复制代码

 

二、警惕 Array.push对原数组数据的修改和Array.concat方法的利用

如下,这是使用Array.push,我们发现其也会把原数组来修改,其哪怕在函数中也不行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let list = [
    { title: "Rad Red" },
    { title: "Lawn" },
    { title: "Party Pink" }
];
 
var addColor = function(title, colors) {
    colors.push({ title: title });
    return colors;
};
 
//
// Add Color is mutating the original list
//
 
console.log(addColor("Glam Green", list).length); // 4
console.log(list.length); // 4

 此时,我们要是有 concat,拼接功能的数组,下面的例子中,使用concat,其表示两个数组拼接在一起。

这里不要想什么效率问题,太底层,你就拼接几个数组,数据量才多大,想啥效率,cpu那些破东西,数据为王

你有本事自己去优化代码啊,你自己又优化不了!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let list = [
    { title: "Rad Red" },
    { title: "Lawn" },
    { title: "Party Pink" }
];
 
const addColor = (title, array) =>
    array.concat({ title });
 
//
// Use array.concat instead, it does not mutate the list
//
 
console.log(addColor("Glam Green", list).length); // 4
console.log(list.length); // 3

这里有一个语法 {title} ,我们看参数名是一个title,而 concat({title}),我们拆分这个语句。

这是个变量名与变量值的问题,title是变量名,其title={Glam Green},而我们又有 title = "Glam Green"

相当于 {title:"Glam Green"},这个语法要理解,关键搞清楚变量名和变量值,以及{ } 运算符的使用技巧

看下面这个代码,很好理解,直接以一个人名来生成一个person,这个不难理解!!

    name = "Tom"
    person = {name}
    console.log(person) // {name: "Tom"}

 

三、函数式编程中的两个关键 Array.map, Array.reduce,Array.filter

 看看上面这两个例子,我们之前使用concat,这是做数组拼接,还有更复杂的方法。

Array中有两个关键函数,一个是对数组进行改变,转换成另一种新的数组,另外一个是对数组进行过滤

它们俩分别是 map 和 filter,我们下面来看看其用法,很简单。

它们都接收一个函数(其只有一个参数),执行时,把数组中的每个值传到里面执行一遍,然后再返回,依次这样执行下去。

 

 当你理解这个模型时,你发现这并没有那么难,你不用去想其怎么实现的,先要具象化,拷贝一份,然后

 如下,要读懂下列这个代码,要知道如何阅读代码:

1. 重点理解item,看见在map里,item就是变量名,每个数组之前是array[i] ,现在直接给单独拿出来,作为item的值来操作;

2. 这个箭头函数没有 { },所以后面指向的就是返回值,在map中,返回值直接就是新的数组的元素;

3. {...item, name} 中 name = "xxx",这个用法要知道,...item,展开,如果是对象,那么展成一个个 name = "xxx",然后重新构建一个对象。

用这种方法,我们不需要手动操作数组,你之后修改数组,要一直使用map这种写法,因为会成生成一份新的数组。

filter方法也是同理,我们现在将这代码给写好,其实一点不难,我们耐心做下去,很好理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let schools = [
    { name: "Yorktown"},
    { name: "Stratford" },
    { name: "Washington & Lee"},
    { name: "Wakefield"}
]
 
// Edit Name with less syntax
 
const editName = (oldName, name, arr) =>
    arr.map(item => (item.name === oldName) ?
        {...item,name} :
        item
    )
 
let updatedSchools = editName("Stratford", "HB Woodlawn", schools)
 
console.log( updatedSchools[1] ) // {name: 'HB Woodlawn'}
console.log( schools[1] ) // {name: 'Stratford'}

below的写法更直接,其函数要返回一个判断表达式,或者说bool值,如果为false,就丢弃。

我们这里直接 (val) => val < 5,不要单纯想着布尔值,关键我们的思维模式,把“val”是数组值,我们直接获取想要的这个值,不要丢弃

我们想的单纯点,避免陷入语法之中,这样写就很简洁,这才是抽象思维。

1
2
3
array = [1,2,3,4,5,6,7,8,9,10]
belowFiveItems = array.filter((val)=>val<5)
console.log(belowFiveItems) //  [1,2,3,4]

Array.reduce

这个返回一个单独的值(single value),这个关键参数,一个是在之前中搜索出来的值,一个是当前的值;

类似依次比较,然后找出你想找出的值,看下面求最大数的例子,其实很好理解。

1
2
3
4
5
array = [1,2,3,4,5,6,7,8,9,10]
 
    maxValue = array.reduce((curMax, curVal)=> curMax > curVal? curMax: curVal)
 
    console.log(maxValue) // 10

 

四、高阶函数

柯里化技术,函数返回一个函数,核心是可以延时调用,如下可以化,其三层函数嵌套

    threeSum = a => b => c =>
        (a + b + c)

    sum = threeSum(1)(2)(3)
    console.log(sum) // 6

我们看这类函数很纠结,为什么写这么别扭,原因很简单,函数式编程,函数为王

我们前端有大量的数据来处理,一个很复杂的数据,我们可以通过函数组合的方式,一次性处理

这样,阅读起来很容易理解,你可以看看代码,这是很好容易阅读的,我们耐心做下去!!

1
2
3
4
5
6
7
8
threeSum = a => b => c =>
    (a + b + c)
 
sumFuncBaseThree = threeSum(1)(2)
sum1 = sumFuncBaseThree(3)
sum2 = sumFuncBaseThree(4)
console.log(sum1) // 6
console.log(sum2) // 7

  

 

posted @   sdklxzciosad  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示