编程|前端开发函数式编程入门


编程|前端开发函数式编程入门
文章图片
编程|前端开发函数式编程入门
文章图片
编程|前端开发函数式编程入门
文章图片
编程|前端开发函数式编程入门
文章图片

函数式编程是一门古老的技术 , 从上个世纪60年代Lisp语言诞生开始 , 各种方言层出不穷 。 各种方言带来欣欣向荣的生态的同时 , 也给兼容性带来很大麻烦 。 于是更种标准化工作也在不断根据现有的实现去整理 , 比如Lisp就定义了Common Lisp规范 , 但是一大分支scheme是独立的分支 。 另一种函数式语言ML , 后来也标准化成Standard ML , 但也拦不住另一门方言ocaml 。 后来的实践干脆成立一个委员会 , 定义一个通用的函数式编程语言 , 这就是Haskell 。 后来Haskell被函数式原教旨主义者认为是纯函数式语言 , 而Lisp ML系都有不符合纯函数式的地方 。
不管纯不纯 , 函数式编程语言因为性能问题 , 一直影响其广泛使用 。 直到单核性能在Pentium 4时代达到顶峰 , 单纯靠提升单线程性能的免费午餐结束 , 函数式编程语言因为其多线程安全性再次火了起来 , 先有Erlang , 后来还有Scala Clojure等 。
函数式编程的思想也不断影响着传统编程语言 , 比如Java 8开始支持lambda表达式 , 而函数式编程的大厦最初就是基于lambda计算构建起来的 。
不过比起后端用Java的同学对于函数式编程思想是可选的 , 对于前端同学变成了必选项 。
前端同学为什么要学习函数式编程思想? React框架的组件从很早开始就是不仅支持类式组件 , 也支持函数式的组件 。
比如下面的类继承的方式更符合大多数学过面向对象编程思想同学的心智:
class Welcome extends React.Component { render() { returnh1Hello {this.props.name/h1;但是 , 完全可以写成下面这样的函数式的组件:
function Welcome(props) { returnh1Hello {props.name/h1;
从React 16.8开始 , React Hooks的出现 , 使得函数式编程思想越来越变得不可或缺 。
比如通过React Hooks , 我们可以这样为函数组件增加一个状态:
import React { useStatefrom 'react';function Example() { // Declare a new state variable which we'll call \"count\" const [count setCount
= useState(0); return (divpYou clicked {count times/pbutton onClick={() =setCount(count + 1)Click me/button/div); 同样我们可以使用useEffect来处理生命周期相关的操作 , 相当于是处理ComponentDidMount:
import React { useState useEffectfrom 'react';function Example() { const [count setCount
= useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() ={ // Update the document title using the browser API document.title = `You clicked ${count times`; ); return (divpYou clicked {count times/pbutton onClick={() =setCount(count + 1)Click me/button/div); 那么 , useState useEffect之类的API跟函数式编程有什么关系呢?
我们可以看下useEffect的API文档:
Mutations subscriptions timers logging and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
Instead use useEffect. The function passed to useEffect will run after the render is committed to the screen. Think of effects as an escape hatch from React’s purely functional world into the imperative world.
所有的可变性、消息订阅、定时器、日志等副作用不能使用在函数组件的渲染过程中 。 useEffect就是React纯函数世界与命令式世界的通道 。
当我们用React写完了前端 , 现在想写个BFF的功能 , 发现serverless也从原本框架套类的套娃模式变成了一个功能只需要一个函数了 。 下面是阿里云serverless HTTP函数的官方例子:
var getRawBody = require('raw-body')module.exports.handler = var getRawBody = require('raw-body')module.exports.handler = function (request response context) { // get requset header var reqHeader = request.headers var headerStr = ' ' for (var key in reqHeader) { headerStr += key + ':' + reqHeader[key
+ ' ' ; // get request info var url = request.url var path = request.path var queries = request.queries var queryStr = '' for (var param in queries) { queryStr += param + \"=\" + queries[param
+ ' ' ; var method = request.method var clientIP = request.clientIP // get request body getRawBody(request function (err data) { var body = data // you can deal with your own logic here // set response var respBody = new Buffer('requestHeader:' + headerStr + '\' + 'url: ' + url + '\' + 'path: ' + path + '\' + 'queries: ' + queryStr + '\' + 'method: ' + method + '\' + 'clientIP: ' + clientIP + '\' + 'body: ' + body + '\') response.setStatusCode(200) response.setHeader('content-type' 'application/json') response.send(respBody) ); 虽然没有需要关注副作用之类的要求 , 但是既然是用函数来写了 , 用函数式思想总比命令式的要好 。