秦粤:“和你聊聊 JS 历史和今年 D2 的语言框架专场”

简介: D2语言框架专场,推荐前端同学们一定要学习下哦。

作者 | 秦粤

点击查看视频

大家好,我是秦粤。阿里巴巴自从2019年加入Ecma后,我们就在Ecma中积极参与推进,决定JavaScript语言发展未来的各种议题,阿里巴巴的议题Error Cause也已经成功的推进到Stage 2。今年在阿里内部由前端委员会牵头也成立了阿里巴巴前端标准化小组,用组织架构保障阿里前端,持续在影响前端生态未来的标准规范上发力。

与此同时我们也特别关注到TC39成员中,不少成员都在关注和推进JavaScript中函数式编程的体验。作为今年D2语言框架会场的出品人,因此我们邀请了RxJS的团队负责人Ben,引入JavaScript函数式编程的议题。另外,今年Ecma组织的大事件ES2020已经发布,我们也将继续邀请TC39的成员Ujjwal,讲解其中有哪些特性值得我们前端同学关注以及这些议题的诞生过程。

函数式编程 in Javascript

函数式编程的思想从1930年提出来已经过去很久了,但大多数工程师使用的场景并不多。函数式编程在JavaScript中几乎是天然就支持的,Brendan Eich参考的语言中包括了函数式编程语言Lisp,因此JavaScript有了函数是一等公民和闭包的概念。

我们大学学习的离散数学,线性代数等等课程,都很容易让我们习惯面向指令编程。我们的代码习惯性都是从上到下,从左到右,加上控制指令block的方式。

ES5之前,如果我们学习了面向原型,会在我们的代码中采用prototype。

ES6和TS后,如果我们学习了面向对象,代码中又会加上Class抽象。

但某种程度而言,这些代码方式都是面向机器友好的。函数式编程是否可以带来一些改变呢?

我自己使用函数式编程的感受是,在面对每个要开发的功能,就像在解数学题。首要是思考数据加工过程如何拆解,初期要不停查工具,看看有哪些函数方法可以给我使用。后期熟练后,会开始用函数式注释,毕竟长时间不看自己原先的代码,同样会忘记。而且不会采用一逗(句号)到底的方式,分段一下。

函数式编程的基础概念,我在此就不啰嗦了。它们是:范畴论,函数一等公民,纯函数,组合,柯里化,等等。

感兴趣的同学可以学习一下:https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/

举个例子

"show me the code",我们来看看具体例子:调用后台API返回了一个数组,其中我们需要对商品的金额进行汇率运算,转换成用户本地的汇率显示。

{
  success: true,
  data: {
    'name': 'ProductsDetail',
    'list': [
      {
        name:'T shirt',
        price:'10.00',
        unit:'$'
      },
      {
        name:'T shirt with logo',
        price:'15.00',
        unit:'$'
      },
      {
        name:'T shirt with brand logo',
        price:'20.00',
        unit:'$'
      },
    ],
  },
}
{
  userCurrency: '¥',
  userCurrencyRate: '6.5',
}

通常,我们会直接写一个循环,或者用UnderscoreJS这样的库将price获取到转化成数字,然后乘以userCurrencyRate。

我们不妨看看函数式的做法,先从简单的函数拆解来看。例如我们乘法函数,我们通常会这样写:

const multiply = function(x,y) {
  return x * y;
}
multiply(3, 5);// 15

而当我们想复用乘法函数,例如固定乘3的函数。我们可以采用JS高级编程的柯里化Currying。

先复习一下柯里化Currying:一个函数将返回一个新的函数,直到接收所有参数。我们用Vanilla JS可以写成:

const multiply = function(x) {
  return function(y) {
    return x * y;
  }
}
const multiply3 = multiply(3);
multiply3(5);// 15

不过这样还有一些不方便,Curry函数这些的写法,我们想用multiply函数multiply(3,5)又不可以了。JS高级编程常见的面试题之一,就是autoCurry,顾名思义根据参数判断函数如何返回。有兴趣的同学可以自己挑战一下实现autoCurry函数,这里我们就直接采用RamdaJS的curry方法。

const R = require('ramda');

const multiply = function(x, y) {
  return x * y;
};
const multiplyAutoCurry = R.curry(multiply);

multiplyAutoCurry(3)(5);// 15
multiplyAutoCurry(3, 5);// 15

有了Curry函数,对于数组我们可以使用map函数,将函数应用到每一项。

const R = require('ramda');

const multiply = function (x, y) {
  return x * y;
};
const multiplyAutoCurry = R.curry(multiply);
const multiply3 = multiplyAutoCurry(3);
R.map(multiply3, [1, 2, 3]);// [3, 6, 9]

因此函数式编程的版本实现,我们就可以写成:

const R = require('ramda');

const multiply = function (x, y) {
  return x * y;
};
const multiplyAutoCurry = R.curry(multiply);
const multiplyCurrency = multiplyAutoCurry(6.5);
const parseIntCurry = R.curry(parseInt);
const parseInt10 = parseIntCurry(R.__, 10);
const currencyConvert = R.compose(multiplyCurrency, parseInt10);

const result = {
  success: true,
  data: {
    name: 'ProductsDetail',
    list: [
      {
        name: 'T shirt',
        price: '10.00',
        unit: '$'
      },
      {
        name: 'T shirt with logo',
        price: '15.00',
        unit: '$'
      },
      {
        name: 'T shirt with brand logo',
        price: '20.00',
        unit: '$'
      },
    ],
  },
};
const priceArray = R.pluck('price', R.prop('list', R.prop('data', result)));// ['10.00', '15.00', '20.00']
R.map(currencyConvert, priceArray);// [ 65, 97.5, 130 ]

由于API返回的结果中price是字符串,为了消除不确定性,我们需要先将price转为数字。这里我们可以用parsefloat,为了演示如何将build-in函数转化成函数式,我选择了parseInt,通过第二个参数传入10解决低版本浏览器兼容性问题。

R.compose是将2个方法组合使用,执行顺序是从右到左。然后我们只需要将我们组合好的工厂函数应用到获取到的价格数组上就行了。

D2 语言框架专场

大家可以发现,我们整个运算过程只使用一次元数据result,这也就是“无副作用”。另外我们将整个过程都转化成了数学解题,而不是让自己像计算机一样思考。前端同学们熟悉的React库也在使用函数式编程的思想,例如单向数据流,State要求immutable。

对于数组和数据流的操作,特别适合函数式操作。ReactiveX就是将数据看成是函数式流处理,因此抽象出Observable, Observer, Subscription等等概念。

import { fromEvent } from 'rxjs';
import { throttleTime, scan } from 'rxjs/operators';

fromEvent(document, 'click')
  .pipe(
    throttleTime(1000),
    scan(count => count + 1, 0)
  )
  .subscribe(count => console.log(`Clicked ${count} times`));

今年D2的语言与框架专场邀请了RxJS:Reactive Extensions For JavaScript团队负责人Ben Lesh,讲解如何利用JS特性重构RxJS,让代码更小更快。

另外函数式在TC39中,也是大厂专家积极讨论的对象,如何优化JS中写函数式的体验,相关议题有:

https://github.com/tc39/proposal-pipeline-operator

https://github.com/tc39/proposal-partial-application

https://github.com/tc39/proposal-pattern-matching

https://github.com/tc39/proposal-record-tuple

同时我们也邀请了Igalia的TC成员Ujjwal,为我们讲解ES2020和ES2021都有哪些可以提升我们JS开发体验的新特性,以及这些特性是如何从TC39中诞生的,我们如何决定影响JS语言的未来。

结语

函数式编程也不是银弹,但在适用的场景,非常好用。大家无妨给自己的工具箱多装备一个函数式编程的工具。我在今年的D2大会语言与框架专场等你。

参考文献:

https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/

Hey Underscore, You're Doing It Wrong!:

https://www.youtube.com/watch?v=m3svKOdZijA

JavaScript函数式编程:

https://github.com/doodlewind/jshistory-cn/blob/master/part-1.md

https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/

image.png


image.png
关注「Alibaba F2E」
把握阿里巴巴前端新动向

相关文章
|
26天前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实战指南
【9月更文挑战第6天】在数字化时代的潮流中,后端开发作为支撑现代Web和移动应用的核心,其重要性不言而喻。本文将深入浅出地介绍如何使用Node.js及其流行的框架Express来搭建一个高效、可扩展的后端服务。通过具体的代码示例和实践技巧,我们将探索如何利用这两个强大的工具提升开发效率和应用性能。无论你是后端开发的新手还是希望提高现有项目质量的老手,这篇文章都将为你提供有价值的见解和指导。
|
2月前
|
JavaScript 前端开发 中间件
构建高效后端服务:Node.js与Express框架的完美搭档
【8月更文挑战第28天】在追求高性能、可扩展和易维护的后端开发领域,Node.js和Express框架的组合提供了一种轻量级且灵活的解决方案。本文将深入探讨如何利用这一组合打造高效的后端服务,并通过实际代码示例展示其实现过程。
|
2月前
|
JavaScript 前端开发 开发者
Vue.js 框架大揭秘:响应式系统、组件化与路由管理,震撼你的前端世界!
【8月更文挑战第27天】Vue.js是一款备受欢迎的前端JavaScript框架,以简洁、灵活和高效著称。本文将从三个方面深入探讨Vue.js:响应式系统、组件化及路由管理。响应式系统为Vue.js的核心特性,能自动追踪数据变动并更新视图。例如,通过简单示例代码展示其响应式特性:`{{ message }}`,当`message`值改变,页面随之自动更新。此外,Vue.js支持组件化设计,允许将复杂界面拆分为独立且可复用的组件,提高代码可维护性和扩展性。如创建一个包含标题与内容的简单组件,并在其他页面中重复利用。
57 3
|
2月前
|
JavaScript 中间件 API
深入浅出Node.js后端框架——Express
【8月更文挑战第27天】在这篇文章中,我们将一起探索Node.js的热门框架Express。Express以其简洁、高效的特点,成为了许多Node.js开发者的首选框架。本文将通过实例引导你了解Express的核心概念和使用方法,让你快速上手构建自己的Web应用。
|
2月前
|
存储 JavaScript NoSQL
构建高效Web应用:使用Node.js和Express框架
【8月更文挑战第30天】本文将引导你了解如何使用Node.js和Express框架快速搭建一个高效的Web应用。通过实际的代码示例,我们将展示如何创建一个简单的API服务,并讨论如何利用中间件来增强应用功能。无论你是新手还是有经验的开发者,这篇文章都将为你提供有价值的见解。
|
5天前
|
Web App开发 JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的深度整合
【9月更文挑战第28天】在现代Web开发领域,Node.js和Express框架的结合已成为打造高性能、易扩展应用的黄金组合。本文将深入探讨如何利用这一技术栈优化Web应用架构,提供具体实践指导,并分析其性能提升的内在机制。通过代码示例,我们将展示从基础搭建到高级功能的实现过程,旨在为开发者提供一条清晰的学习路径,以实现技术升级和项目效率的双重提升。
14 3
|
7天前
|
前端开发 JavaScript API
React、Vue.js 和 Angular前端三大框架对比与选择
前端框架是用于构建用户界面的工具和库,它提供组件化结构、数据绑定、路由管理和状态管理等功能,帮助开发者高效地创建和维护 web 应用的前端部分。常见的前端框架如 React、Vue.js 和 Angular,能够提高开发效率并促进团队协作。
24 4
|
9天前
|
JavaScript 前端开发
常用的 JavaScript 框架和库
常用的 JavaScript 框架和库
13 6
|
9天前
|
前端开发 JavaScript 开发者
React 和 Vue.js 框架的区别是什么?
React 和 Vue.js 框架的区别是什么?
|
14天前
|
缓存 监控 JavaScript
构建高效后端服务:Node.js与Express框架的完美结合
【9月更文挑战第18天】在数字化时代的浪潮中,后端服务的效率和稳定性成为了企业竞争力的关键。本文将深入探讨如何使用Node.js和Express框架来构建一个既高效又稳定的后端服务,同时通过实际代码示例,展示如何优化性能并确保服务的高可用性。
下一篇
无影云桌面