函数式编程

函数式

一、 函数式编程的出现

  • 编码发展历程: 命令(脚本)式 =》面向对象(进一步提高了模块的概念)=》函数式编程
1. 问题的出现 -面试题
  // 面试题: 上接浏览器原理 - 参数 parse
  // 1. 数组在url中的展示形式
  // location.search获取参数 => '?name[]=progressive$%coding'
  // 2 参数提取拼接成数组
  // ['progressive', '']
  // 3. 手写一个方法转换成对象数组
  // [{name: 'Progerssive Coding'}, {name: 'Objective Coding'}, {name: 'Function Coding'}]
  const _array = ['Progerssive Coding', 'Objective Coding', 'Function Coding']
  const _objArr = []

  const nameParser = () => {
    array.forEach(item => {
      let names = item.split('$%')
      let newName = []
      names.forEach(name => {
        let nameItem = name[0].toUpperCase() + name.slice(1)
        newNames.push(nameItem)
      })
    })
    objArr.push({
      name: newName.join(' ')
    })
    return objArr
  }

  console.log(nameParser(_array, _objArr))
  // 问题:
  // 1 过程存在逻辑包裹  看完整段代码才知道在干啥
  // 2 存在一堆临时变量并且首尾是封闭的 迭代拓展难度大
2.解决方案
// step1 需求分析 =》从数组到对象数组 =》 字符串 =》 对象
// nameParser =》 [objHelper::string>object]
// step2 模块功能明确 => objHelper => formatName + assembleObj
// step3 功能拆分 =》objHelper = [(split+capitalize+join)] + assembleObj
// step4 代码实现
const _array = ['Progerssive$%Coding', 'Objective$%Coding', 'Function$%Coding']
// 原子操作
const assembleObj = (key, x) => {
  let obj = {}
  obj[key] = x
  return obj
}

const capitalize = name => name[0].toUpperCase() + name.splice(1)

// 组装描述
const formatName = 组装合并(join(''), map(capitalize), split('$%'))
const objHelper = 组装合并(assmebleObj('name'), formatName)
const nameParser = map(objHelper)

// 使用
nameParser(_array)

// 面试题 正确的遍历 for forEach map filter some 
// 本质作用 for是通用遍历 foreach的存在是为了对一个数组进行遍历然后做相应的逻辑处理
// map的功能在于生成数组
let class = 'functional'
let isOvered = false
classArr.forEach(item => {
  isOvered = item === class
})

二、函数式编程的原理特点

1.什么是函数式编程的原理
  • 加法结合律 因式分解 完全平方公式 这三者其实在描述一个原子组合的变化 原子操作组合方式做了改变
  • 水源 =》 (水管+走线)=》浴缸
2.理论思想
a. 函数是一等公民 函数是实实在在的逻辑功能实现的落脚点 在过程式编程中并不是每行代码都有功能 (实现+拼接)*函数
b. 声明式编程 声明需求 语义化 更像是语言在描述需求 react vue3 就是通过一个一个独立的纯函数钩子,在内部做一些独立的子需求模块
c. 惰性执行
// 惰性函数
const program = name => {
  if (name === 'progressive') {
    return program = () ={
      console.log('progressive')
    }
  } else if (name === 'objective') {
    return program = () ={
      console.log('objective')
    }
  } else {
    return program = () ={
      console.log('functional')
    }
  }
}

program('progressive')()
console.log('lazy')
program()
// 以上会打印两次progressive 函数变量提升
3.无状态与无副作用
  • 无状态 - 幂等 - 数据不可变 函数内部坚决不可以直接操作整个系统中的任何参数变量的数据

三、实际开发

1.纯函数改造
const _class = {
  name: 'objective'
}
// 函数内部引入外部变量  违反了无状态原则
const score = str => _class.name + ':' + str
const changeClass = (obj, name) => obj.name = name
changeClass(_class, 'functional')
score('good!')

const _class = {
  name: 'objective'
}

const score = (obj, name) => obj.name + ':' + str  //不依赖外部变量
const changeClass = (obj, name) => ({...obj, name})  //未修改外部变量
changeClass(_class, 'functional')
score(_class, 'good')
2 流水线组装 加工 组装
// f(x, y, z) -> f(x)(y)(z)
const sum = (x, y) => {
  return x+y
}
sum(1,2)
const add = x => {
  return y => {
    return x + y
  }
}
add(1)(2)

const fetch = ajax(method, url, params)
const request = ajax(method)
const fetch = request(url)
ajax(method)(url)(params)
  • 面试题: 手写构造可拆分传参的累加函数
    add(1)(2)(3)
// 构造柯里化结构
// 输入层处理外部arguments =》 类数组形态处理
// 传入参数无线拓展 =》 递归内层逻辑 =》 返回函数
// 主功能实现 =》 累加
// 输出
const add = function ()  {
  // 输入
  let args = Array.prototype.slice.call(arguments)
  // 内层处理
  let inner = function () {
    args.push(...arguments)
    return inner
  }
  inner.toString = function () {
    return args.reduced((pre, cur) => {
      return prev + cur
    })
  }
  return inner
}
add(1)(2)(3)(4)
b.流水线
const compose = (f, g) => x => f(g(x))

const sum1 = x => x + 1
const sum2 = x => x + 2
const sum12 = compose(sum1, sum2)
sum12(1)
  • 实际实现应用
// 命令式
trim(reverse(toUpperCase(map(arr))))
// 面向对象
arr.map().toUpperCase().reverse().trim()
// 函数式
const result = compose(trim, reverse, toupperCase, map)
pipe(map, toUpperCase, reverse, trim)

四、BOX与函子

// 一封信
class Mail {
  constructor (content) {
    this.content = content
  }
  map (fn) {
    return new Mail(fn(this.content))
  }
}

// 拆开信
let mail1 = new Mail('love')
// 读了信
let mail2 = mail1.map(function(fn) {
  return read(mail)
})
// 烧了信
let mail3 = mail.map(function(mail) {
  return burn(mail)
})
// 老师查寝时候
mail3.map(function(mail) {
  return check(mail)
})
// 链式
new Mail('love').map(read).map(burn).map(check)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React是一个用于构建用户界面的JavaScript库。它采用了组件化的开发方,使得开发者可以将界面拆分成独立的、可复用的组件。在React中,函数编程是一种常见的编程,它强调使用纯函数来构建应用。 函数编程是一种编程,它将计算视为数学函数的求值过程。在函数编程中,函数被视为一等公民,可以作为参数传递给其他函数,也可以作为返回值返回。函数编程强调不可变性和无副作用,即函数的执行不会改变外部状态。 在React中,函数编程被广泛应用于组件的开发。使用函数编程的方,我们可以将组件定义为纯函数,接收一些输入参数(称为props),并返回一个描述组件界面的React元素。这种方使得组件的开发更加简洁、可测试和可维护。 函数编程在React中的一些特点包括: 1. 纯函数:组件函数应该是纯函数,即相同的输入应该始终产生相同的输出,而且不应该有副作用。 2. 无状态组件:函数组件通常是无状态的,即它们不会保存任何状态信息,只依赖于传入的props进行渲染。 3. 高阶组件:函数编程可以使用高阶组件(Higher-Order Components)来增强组件的功能,例如添加共享的逻辑或状态管理。 总结一下,React中的函数编程是一种将组件定义为纯函数的开发方,它强调不可变性和无副作用,使得组件的开发更加简洁、可测试和可维护。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值