通过利用immutability的能力编写更安全和更整洁的代码

原文:Write safer and cleaner code by leveraging the power of “Immutability”

译者:neal1991

welcome to star my articles-translator, providing you advanced articles translation. Any suggestion, please issue or contact me

LICENSE: MIT

Immutability是函数式编程的重要基础之一。它允许你能编写更安全以及更整洁的代码。我将会通过一些JavaScript例子来向你展示如何来达到immutability。

根据维基百科:

不可变对象是一个在创建之后不能修改其状态的对象。这正与可变对象相反,它能够在创建之后被修改。在某些情况下,对象被认为是不可变的,即使其内部的某些属性发生改变,但是从外部的角度来看这个对象的状态看起来还是没有发生变化的。

Immutable数组

数组是理解immutability如何工作的很好的起点。让我们一起来看一看。

const arrayA = [1, 2, 3];
arrayA.push(4); const arrayB = arrayA;
arrayB.push(5); console.log(arrayA); // [1, 2, 3, 4, 5]
console.log(arrayB); // [1, 2, 3, 4, 5]

这个例子将arrayA的引用分配给arrayB,因此这个push方法在这两个变量中都会添加5这个值。我们的代码间接地修改其它的值,这并不是我们想要的。这也违反了immutability的原则。

我们可以通过使用 slice函数将我们的例子提升为immutable,并且这个代码的行为也产生了变化。

const arrayA = [1, 2, 3];
arrayA.push(4); const arrayB = arrayA.slice(0);
arrayB.push(5); console.log(arrayA); // [1, 2, 3, 4]
console.log(arrayB); // [1, 2, 3, 4, 5]

这正是我们想要的。代码没有改变其它值。

提醒:当你使用 push 向数组添加一个值的时候,你是在改变这个数组。你想要避免修改变量,因为这可能会给你的代码带来负面影响。 slice函数能够返回数组的拷贝。

函数

现在你知道如何避免修改其它值。那么你知道如何写“纯”函数了嘛?纯函数是对于一个不会又任何副作用以及不会改变状态的函数另一个称呼。

我们来看一个利用数组示例中相同原理的函数。 首先,我们创建一个改变其它值的函数,然后我们将该函数改进为“纯”。

const add = (arrayInput, value) => {
arrayInput.push(value); return arrayInput;
};
const array = [1, 2, 3]; console.log(add(array, 4)); // [1, 2, 3, 4]
console.log(add(array, 5)); // [1, 2, 3, 4, 5]

因此再一次,我们修改我们的输入,这会产生一个无法预测的函数。在函数式编程的世界中,对于函数有一个黄金法则:使用相同输入的函数应该返回相同的结果。

上述的函数违反了这一黄金法则。每一次我们的add函数被调用的时候,它就会修改这个array变量,结果也就不同了。

让我们一起看看看如何改变我们add函数的事先,因此让其成为immutable。

const add = (arrayInput, value) => {
const copiedArray = arrayInput.slice(0);
copiedArray.push(value); return copiedArray;
}; const array = [1, 2, 3];
const resultA = add(array, 4);
console.log(resultA); // [1, 2, 3, 4]
const resultB = add(array, 5);
console.log(resultB); // [1, 2, 3, 5]

现在我们可以调用我们的函数多次,并且可以预期在相同输入的时候,输出都是相同的。这是因为我们不再会修改这个array变量。我们能够将这个函数成为“纯函数”。

注意:你也能使用concat,而不是slice以及push。

因此:arrayInput.concat(value)

我们能够利用ES6中的[扩展语法]((https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Operators/Spread_operator)来缩短函数。

const add = (arrayInput, value) => […arrayInput, value];

并发

NodeJS应用使用了一个叫做并发的概念。一个并发操作意味着两个计算能够能够同时进行并且不用考虑另外一个。如果这里有两个线程的话,第二个计算不需要等到第一个计算完成才能只需执行。

NodeJS通过event-loop让并发变得可能。event-loop会重复获取一个事件,并且每次会激活任一一个事件处理器来监听事件。这个模型允许NodeJS应用处理大量的请求。如果你想了解更多,阅读这篇关于event-loop的文章。

Immutability和并发之间有什么关系呢?因为做个操作能够在函数的作用域外以并发的方式改变值,这会产生一个不可靠的输出以及无法预期的结果。意识到函数可能会在作用域外修改变量,因此这可能会非常危险的。

下一步

Immutability对于你理解和学习函数式编程是非常重要的一个概念。你可能希望了解mmutableJS](https://facebook.github.io/immutable-js),其由Facebook开发者编写。这个library提供了某些不可变的数据机构,比如 Map, Set以及List.

[Immutable.js, persistent data structures and structural sharing](Immutable.js, persistent data structures and structural sharing)(译者注:墙外地址)

通过利用immutability的能力编写更安全和更整洁的代码的更多相关文章

  1. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

  2. 利用Warensoft Stock Service编写高频交易软件

    利用Warensoft Stock Service编写高频交易软件 无论是哪种交易软件,对于程序员来讲,最麻烦的就是去实现各种算法.本文以SAR算法的实现过程为例,为大家说明如何使用Warensoft ...

  3. 利用Warensoft Stock Service编写高频交易软件--DEMO

    利用Warensoft Stock Service编写高频交易软件 无论是哪种交易软件,对于程序员来讲,最麻烦的就是去实现各种算法.本文以SAR算法的实现过程为例,为大家说明如何使用Warensoft ...

  4. 第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码

    第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码 scrapy-redis是一个可以scrapy结合redis搭建分布式爬虫的开 ...

  5. C++:利用如下公式,编写函数计算∏的值,直到最后一项的绝对值小于e,主程序接收从键盘输入的e,输出∏的值(保留5位小数)。 ∏/4 = 1-1/3+1/5-1/7...

    利用如下公式,编写函数计算∏的值,直到最后一项的绝对值小于e,主程序接收从键盘输入的e,输出∏的值(保留5位小数). ∏/4 = 1-1/3+1/5-1/7... #include <iostr ...

  6. 阿里云MVP:开发者的超能力,用技术创造更好世界

    阿里云MVP:开发者的超能力,用技术创造更好世界 2019年3月,第8期阿里云MVP(最有价值专家)完成终审,截至目前,全球已有27个国家和地区.近500位云计算专家和优秀开发者成为阿里云MVP.阿里 ...

  7. iOS书摘之编写高质量iOS与OS X代码的52个有效方法

    来自<Effective Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法>一书的摘要总结 一.熟悉Objective-C 了解Objective-C语言的起源 ...

  8. 专访|HPE测试中心总监徐盛:测试新思维-DevOps,持续测试,更敏捷,更快速

    2016年7月22日,「HPE&msup软件技术开放日」将在上海浦东新区,张江高科技园区纳贤路799号科荣大厦小楼2楼举办,msup携手HPE揭秘全球测试中心背后的12条技术实践. 徐盛:HP ...

  9. 第一章 熟悉Objective -C 编写高质量iOS与OS X代码的52 个有效方法

    第一章 熟悉Objective -C   编写高质量iOS与OS  X代码的52 个有效方法   第一条: 了解Objective-C 语言的起源 关键区别在于 :使用消息结构的语言,其运行时所应执行 ...

随机推荐

  1. 面试题常考&必考之--js中的对象的浅拷贝和深拷贝(克隆,复制)(下)

    这里主要是讲深拷贝: 深拷贝:个人理解就是拷贝所有的层级 1.像对象里再放数组和对象这些叫引用值.开始我们先判断大对象中是否有引用值(数组和小对象), 然后在判断引用值是数组还是对象 2.开始啦: 1 ...

  2. 组件的属性props

    组件的属性props 是不能自己改的,一般是从外面传进来.在组件的视图中用,this.props.XXX 表示该组件的XXX 属性

  3. ORM详解,ORM Object relation mapping (对象关系映射)

  4. CF1081G Mergesort Strikes Back

    题目大意: 给定\(n\),\(k\),\(mod\),求随机排列在\(k\)层归并排序下逆序对的期望. 题解 考虑这\(k\)层归并会把序列分成若干个块. 这些块内的顺序是原序列的相对顺序,我们要把 ...

  5. iOS模拟器Custom Location被重置解决方案

    转自王中周的技术博客 问题说明   在做地图类应用时,经常需要用到位置模拟功能.iOS模拟器提供了该功能,我们可以设置指定的经纬度,选中模拟器后,按照以下菜单层次进入即可设置: Debug --> ...

  6. ORACLE Physical Standby DG 之fail over

    SQL> select thread#, low_sequence#, high_sequence# from v$archive_gap;确认下是否存在日志间隙,发现gap现象,说明failo ...

  7. tar 打包文件

    tar支持通配符, 可以用* ?等来指定多个文件 在指明压缩文件名的时候, 一定要带上 -f选项 压缩文件名中间 最好不要带特殊符号, 如& ? * +等, shell bash 会作一些特殊 ...

  8. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_02 泛型_4_定义和使用含有泛型的方法

    泛型方法 泛型也可以用在方法上 测试 调用的时候,可以传递多种数据类型 . 泛型的静态方法

  9. python接口自动化:https请求,取消警告

    实现代码如下: import requests r=requests.get('https://www.baidu.com',verify=False) rr=r.content.decode() p ...

  10. MyBatis Generator 生成的example 使用 and or 简单混合查询

    MyBatis Generator 生成的example 使用 and or 简单混合查询 参考博客:https://www.cnblogs.com/kangping/p/6001519.html 简 ...