前言
我们虽然之前老是听说过“函数式编程”,但一直不能理解,我们静下心来研究了一下,才发现这些东西真的很巧妙。
在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,我们发现其也会把原数组来修改,其哪怕在函数中也不行。
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那些破东西,数据为王
你有本事自己去优化代码啊,你自己又优化不了!!
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方法也是同理,我们现在将这代码给写好,其实一点不难,我们耐心做下去,很好理解。
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”是数组值,我们直接获取想要的这个值,不要丢弃
我们想的单纯点,避免陷入语法之中,这样写就很简洁,这才是抽象思维。
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),这个关键参数,一个是在之前中搜索出来的值,一个是当前的值;
类似依次比较,然后找出你想找出的值,看下面求最大数的例子,其实很好理解。
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
我们看这类函数很纠结,为什么写这么别扭,原因很简单,函数式编程,函数为王
我们前端有大量的数据来处理,一个很复杂的数据,我们可以通过函数组合的方式,一次性处理
这样,阅读起来很容易理解,你可以看看代码,这是很好容易阅读的,我们耐心做下去!!
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
标签:编程,console,name,title,JavaScript,log,数组,函数 From: https://www.cnblogs.com/qwe-asd-zxc-nm/p/17645710.html