秦粤:“和你聊聊 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」
把握阿里巴巴前端新动向

相关文章
|
2月前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端框架
【10月更文挑战第34天】在数字化时代,后端开发如同一座桥梁,连接着用户界面与数据处理的两端。本文将通过Node.js这一轻量级、高效的平台,带领读者领略后端框架的魅力。我们将从基础概念出发,逐步深入到实战应用,最后探讨如何通过代码示例来巩固学习成果,使读者能够在理论与实践之间架起自己的桥梁。
|
3月前
|
JavaScript 前端开发 中间件
探索后端技术:Node.js与Express框架的完美融合
【10月更文挑战第7天】 在当今数字化时代,Web应用已成为日常生活不可或缺的一部分。本文将深入探讨后端技术的两大重要角色——Node.js和Express框架,分析它们如何通过其独特的特性和优势,为现代Web开发提供强大支持。我们将从Node.js的非阻塞I/O和事件驱动机制,到Express框架的简洁路由和中间件特性,全面解析它们的工作原理及应用场景。此外,本文还将分享一些实际开发中的小技巧,帮助你更有效地利用这些技术构建高效、可扩展的Web应用。无论你是刚入门的新手,还是经验丰富的开发者,相信这篇文章都能为你带来新的启发和思考。
|
8天前
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
93 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
2月前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
2月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
43 2
|
3月前
|
JavaScript 前端开发 API
Vue.js:现代前端开发的强大框架
【10月更文挑战第11天】Vue.js:现代前端开发的强大框架
91 41
|
2月前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
2月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
56 4
|
2月前
|
JavaScript 中间件 API
Node.js进阶:Koa框架下的RESTful API设计与实现
【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
56 4
|
3月前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的完美结合
【10月更文挑战第21天】本文将引导你走进Node.js和Express框架的世界,探索它们如何共同打造一个高效、可扩展的后端服务。通过深入浅出的解释和实际代码示例,我们将一起理解这一组合的魅力所在,并学习如何利用它们来构建现代Web应用。
75 1