我们需要注意的 immutable 操作

综合技术 前端小站 (源链)

作者简介:hustcc 蚂蚁金服·数据体验技术团队

immutable 是什么?不变的、一成不变的。在 Javascript 中一般指一个变量在经过一个 function 处理之后,可以保持入参数据不变。

一、什么是 immutable?

举个真实日常例子:前两天,在业务代码中,需要获得数据的中位数,并使用 echarts 绘制出中位线,辅助分析。写代码之前,先找了一下 中位线 的定义。

对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,通常取最中间的两个数值的平均值作为中位数。

哦,挺简单,于是奋笔疾书(其实是 github 上的 代码片段

/**
 * 求取数组中的中位数
 * [1, 2, 3, 4, 4] -> 3
 * [1, 2, 3, 4, 5, 6] -> 3.5
 */
const calculateMedian(arr) => {
  // 1. 排序
  arr.sort((a, b) => a - b);

  const half = Math.floor(arr.length / 2);

  // 2. 按照中位数定义计算
  // 奇数长度则中间值,偶数长度则中间两个数的平均值
  return arr.length % 2 !== 0 ?
    arr[half] :
    (arr[half - 1] + arr[half]) / 2.0;
}

这段代码的问题在于函数是 mutable 的:

当经过函数 calculateMedian 求取数组 [5, 4, 3, 2, 1] 的中位数的时候,导致入参数组变成了 [1, 2, 3, 4, 5]。导致后续的代码拿到的数组,都是经过排序的,数据都是混乱的。

上述代码只需要修改一个地方即可:

const newArr = [].concat(arr).sort((a, b) => a - b);

其中 [].concat(arr) 达到的效果就是代码的 immutable。

通过这样的一个实际例子,我想应该很容易理解 mutable 代码造成的影响是什么?

  • 数据污染:经过一个方法,数据就变化了,多么可怕。
  • 数据不可控:数据不仅仅是被修改,而且我们没法控制数据被修改的规律。
  • debug 黑洞:一般的 bug,如果了解业务,可能不用 debugger 就能定位一二;mutable 产生的 bug,没办法,新增代码一句句 F10 吧。

二、常见的原因

很多情况下,道理我们都懂,但是还是会不经意写出 mutable 的代码。分为几种情况,看起来清晰一些吧!

1. 意识不清晰

很多开发者在写代码的时候,没有从全局胜寒意识到函数必须保证 immutable,只在乎自己的函数输入输出符合要求。

开发者需要有时刻警惕的意识,一旦涉及到 object 的操作,先提醒自己注意不可变。特别是对于公共模块的开发,开源项目的开发,养成“变道就打转向灯的好习惯”。

2. 函数理解不清晰

Array 常见的函数 push、pop、shift 等,一般都能理解它们是会修改原数组数据,是 mutable 的函数。

但是对于上述例子中的 sort 函数应该就是理解上容易产生歧义(自己之前一直以为是生成一个新的数组,写完这篇,我去搜索了整个业务代码)。同样的,容易产生歧义的函数包括:

  • sort
  • reverse
  • fill
  • splice
  • delete

注意:Array 中 immutable 函数很多,以上几个函数是功能上容易误解的。

3. 使用“不靠谱”的开源库

GitHub 真是个好东西,只要你能想到的代码,基本都有参考的,特别是 JavaScript 语言的。

但是你永远不知道你使用的轮子是不是仅仅是一个课堂作业练手的。在使用一个开源模块的时候,需要观察:

  • 单测是否完善 :不是指单测是不是绿色(pass),而是看 单测代码是否靠谱

在完善的单测可以看到:

  1. 项目实际的使用方式,这些很可能是 README 中无法完整写出来的东西。
  2. 理解项目的模块划分,组织架构。
  3. 开发者在项目代码中扣住的开发细节点。

比如,如果 immutable 是项目的一个重要特性之一,那么在单测代码中一定会反映出来。

  • npm 下载量

就像在网上购物一样,比较懒的购物者,直接买订单数最多的爆款。

  • issues

可以关注在 issue 处理速度、issue 中搜索关键字,可以大概知道是否存在这些问题。

  • 何妨 review 一下

如果代码简单,可以简单 review 一下,抓住代码实现的关键点。

三、如何写 immutable 的代码

既然要写 immutable 的代码,那我们应该怎么做?

1. 靠谱开源项目

  1. immutability-helper :基于原始 Array 和 Object 的 immutable 操作,很好用。
  2. js-joda :日期 Date immutable 方法。
  3. immutable-js :Facebook 的 immutable 模块,定义了新的数据结构,使用成本相对高一点点。
  4. immutability-helper-x :包装 immutable-helper,使用更友好。
  5. immu :基于 Proxy 的 immutable 模块,思路新颖,但是兼容性差一点。

2. 单测约束

针对开头的 calculateMedian 函数,写一个单测:

describe('calculateMedian', () => {
  test('immutable', () => {
    const a = [5, 4, 3, 2, 1];
    const aClone = a.slice();
    expect(calculateMedian(a)).toBe(3);
    // 保证不能被修改!
    expect(a).toEqual(aClone);
  });
});

单测约束之后,以后其他人修改这么代码导致 mutable 的时候,也会 ci 报错的,保证这个方法的长治久安。

除此之外,开启 Eslint 工具,也可以对 Object 的 mutable 自动告警。

3. 解构和 spread 语法

解构是 spread 预发是 ES6 中的新语法,也是我个人用的非常多的,一般代码的 immutable 写法,都可以满足。

  • Object 解构与 spread

比如我们有一个用户信息 A(几十项信息),然后需要创建一个用户信息 userB,除 id、name 不一样之外,其他都和 userA 一致。

const userA = {
  id: 1,
  name: 'hustcc',
  addr: 'Hangzhou',
  birth: '1992-08-01',
  // ...
  // 很多的数据不列出了
};

// 结构和 spread 写法创建 userB
const userB = {
  ...userA,
  id: 2,
  name: 'ProtoTeam',
};
  • 数组 immutable 操作
const arr = [1, 2, 3, 4, 5];

// push 操作
const arrPush = [
  ...arr,
  6,
];

// shift 操作
const [e, ...arrShift] = arr;

// concat

const arrConcat = [...arr, ...arr];

四、最后

在 react + redux 技术栈下,不可变数据结构是大家都提倡的做法,所以又很多框架层面的东西帮我们处理了这些事情。

但是实际上,我们在平时的业务代码开发中,就需要有 immutable 的意识,善用 ES6 语法,就可以解决我们大部分的场景。

对我们团队感兴趣的可以关注专栏,关注 github 或者发送简历至’tao.qit####alibaba-inc.com’.replace(‘####’, ‘@’),欢迎有志之士加入~

原文地址: https:// github.com/ProtoTeam/bl og/blob/master/201803/3.md

您可能感兴趣的

Where can I learn Web programming from the beginni... I tried doing tutorials but it is unorganized and unstructured, where can I learn PHP from beginner to master? I'm looking for a site like www.w3c...
Yandex open sources its “crown jewel” ... The Russian tech giant is open sourcing its gradient boosting library, which it uses internally to boost predictive algorithms. Credit: ...
为什么甲骨文对待开源要搞两面派?一个字:钱!... 甲骨文爱开源,除了这个数据库巨头讨厌开源的时候,当然是这样的。从最近它游说美国联邦政府反对开源这一做法来看,似乎大部分时间它是讨厌开源的。 没错,甲骨文最近加入了云原生计算基金会(CNCF),加大对 Kubernetes 的支持力度;没错,它长期以来都在支持着 Linux(并向其贡献...
Using JavaScript to hack the web There's no lack of online resources for JavaScript, from courses that teach you the basics to tutorials on app creation. In this article—which doesn't...
经验分享 | 关于“入侵检测”的一些想法... *本文原创作者:PgHook,属于FreeBuf原创奖励计划,未经许可禁止转载 离开长沙的时候写了一篇文章“左右互博:站在攻击者的角度来做防护”(freebuf上可以找到),一晃已经是三年了。这三年接触了很多东西,自己也有过很多想法,但实际上去做的却很少。花了很多时间,做了一款插件化的...
责编内容来自:前端小站 (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 我们需要注意的 immutable 操作



专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录