详解用函数式编程对JavaScript进行断舍离


Posted in Javascript onSeptember 18, 2017

我和JavaScript

从1997年网景的Navigator 3浏览器开始就开始使用JavaScript。当时,JavaScript还只能做一些很简单的事情。我记得最酷的就是用JavaScript实现mouseover特性,在那个时候已经算得上是高科技了!当鼠标移过去之后,文本内容就神奇的改变了。因为当时都是pre-DHTML,你根本不需要隐藏或则显示DOM元素。

关于DHTML

DHTML是Dynamic HTML的简称,就是动态的html(标准通用标记语言下的一个应用),是相对传统的静态的html而言的一种制作网页的概念。所谓动态HTML(Dynamic HTML,简称DHTML),其实并不是一门新的语言,它只是HTML、CSS和客户端脚本的一种集成,即一个页面中包括html+css+javascript(或其它客户端脚本),其中css和客户端脚本是直接在页面上写而不是链接上相关文件。

在那个时候,JavaScript的演化很慢,主要应用在表单验证。因此,不像今天这么火爆,并没有引起太多的关注。可以说只是一个锦上添花的附加物,你需要确保在浏览器禁用JavaScript之后,你的应用依然可以正常使用。再往后,框架一个接着一个出现:jQuery,Knockout, Angular, React, Vue, 等等。

同样,JavaScript也在加速演化。我们才使用ES6不久,现在人们几乎已经跳过ES7,开始讨论ES8了。

并且,我们有很多替代品,比如TypeScript,CoffeScript,ClojureScript, ELM,等等。

我们已经被太多的框架和语言所淹没,很难去跟踪和掌握所有的语言和框架。

错误路线

当JavaScript逐渐成熟,面向对象编程(OOP)的概念也渗入进来,而且我曾经很喜欢。

我开始尝试所有不同的方法来创建类,我最终也可以正确的使用继承。我对自己说:JavaScript开始真的像一个语言了!

但是,直到多年以后我发现OOP是JavaScript引入的最糟糕的一个设计!

我尝试将我对C#的理解带入到JavaScript中去。一开始充满期待,但是后来发现真的太复杂,太烧脑了。

这主要是因为JavaScript的原型继承和C#不一样,我已经习惯于每天编写类似于console.log(this)这样飘逸的代码。但是现在呢?如果我一不小心没按照规则来,那将会给我带来噩梦。私有方法和私有值必须要在名字前面加上下划线,甚至必须用闭包来保证私有性。

因此,不仅OOP导致了很多问题,同时也由于添加OOP带来了很多新的问题。

函数式编程

一开始我并不理解。我可以阅读并理解这些用函数式编写的代码,但是不知道为什么!最终,我强迫我自己去学习它。

函数式语言给了我一个全新的视角,让我从一个完全不同的方式去看待编程。

一开始会感到不自然,需要时间去适应。所有的定义都是基于函数,值不可更改,无状态。我用函数式的思维去解决问题。因为不熟悉,我花了更长的时间去学习。渐渐地,我熟练掌握了使用函数式的方法去编程。并且,我也知道所有代码这样编写的内在含义。

我的代码更加简洁了,而且容易复用。渐渐的,我以前使用的那些语言特性从代码中消失了,我的代码看上去完像是用另一个语言编写。我还在用JavaScript吗?

1. 不再使用var

我用const替代了var。通过函数式的设计,我的函数都是纯(pure)的。不会再去对一个变量进行值的变更操作,同样也是为了确保不会对其操作。

我会检查代码确保每一个var,甚至let,所有声明都使用const。

2. 没有for循环

在学习程序语言的时候,我们一开始就会学到for循环。但是自从学习了函数式编程,我将for循环都改成了使用filter, map和reduce来实现。对于那些需要一些额外计算的需求,我会使用递归或则第三方库比如lazy.js。

如今我的代码里面完全没有for循环了,如果你看到了,告诉我我会把它消除。

3. if也可以被简化

我开始停止在if里面编写大块大块的代码。我将里面的逻辑抽取出来单独放在一个函数中。这样,我们就可以将if用三元算子(a?b:c)来简化。

如今我的代码里面几乎没有if语句。为了方便其他开发者理解我的代码,我很少使用它。

4. 和switch说拜拜

同样,我也不喜欢用switch,而是寻找一个函数式的写法。

我也很喜欢用Ramda的cond算子来替代swtich。

5. 不在担心this

对的,你没有听错!我们也可以完全消除this。

函数式的JavaScript可以让你完全抛弃使用烦人的this
现在只有数据和函数,甚至数据不过是函数的一种特殊表达形式,你再也不需要this了。我开始将对象理解为函数式语言中状态(state)和函数。我甚至不需要把状态或则函数和对象绑定到一起,就像OOP中那样。

面向对象的设计不是必须的

现在往回看,我发现面型对象编程带来的复杂度真的是不必要的。我可以使用函数式语言实现同样的功能,完成相同的任务。而且,代码更加轻简,因为不在需要将这些复杂的对象传来传去。只有数据和函数,而且因为函数没有和对象绑定,更加容易复用。我不在需要担心传统的原型继承带来的所有的问题,JavaScript设计的并不好。

JavaScript缺乏私有、公有、内部或则被保护这类访问控制器也不再是一个问题。访问控制器是用来解决由于引入面向对象编程而设计的。在函数式的JavaScript中,这些问题不复存在。

总结

我的代码现在看上去完全不同。它包含了很多纯函数,我将它们做成不同的ES6模块。这些函数可以被使用来构建更加复杂的函数。很大一部分函数都是很简单的一行lambda表达式。

现在我看待软件的思维也变了:输入是一个数据流,然后程序作用到该数据流上对数据进行各种操作,然后返回新的数据。

函数式设计对程序语言的影响以及无处不在,C#中的LINQ就是一个最佳的例子。同样Java 8也引入了函数式语言的特性。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 添加和移除函数的通用方法
Oct 20 Javascript
jQuery 顶部导航跟随滚动条滚动固定浮动在顶部
Jun 06 Javascript
sogou地图API用法实例教程
Sep 11 Javascript
学习javascript文件加载优化
Feb 19 Javascript
JavaScript实现打开链接页面的方式汇总
Jun 02 Javascript
JS中解决谷歌浏览器记住密码输入框颜色改变功能
Feb 13 Javascript
react 父组件与子组件之间的值传递的方法
Sep 14 Javascript
详解vue项目的构建,打包,发布全过程
Nov 23 Javascript
JS实现二维数组横纵列转置的方法
Apr 17 Javascript
ES6 Symbol数据类型的应用实例分析
Jun 26 Javascript
jquery分页优化操作实例分析
Aug 23 jQuery
基于redis的小程序登录实现方法流程分析
May 25 Javascript
深入浅析JavaScript中的RegExp对象
Sep 18 #Javascript
JavaScript 数组的进化与性能分析
Sep 18 #Javascript
JavaScript实现HTML5游戏断线自动重连的方法
Sep 18 #Javascript
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
Sep 18 #Javascript
BetterScroll 在移动端滚动场景的应用
Sep 18 #Javascript
Windows下Node.js安装及环境配置方法
Sep 18 #Javascript
jQuery选择器之子元素选择器详解
Sep 18 #jQuery
You might like
PHP中10个不常见却非常有用的函数
2010/03/21 PHP
PHP错误抑制符(@)导致引用传参失败Bug的分析
2011/05/02 PHP
使用纯php代码实现页面伪静态的方法
2015/07/25 PHP
php 实现Hash表功能实例详解
2016/11/29 PHP
PHP微信分享开发详解
2017/01/14 PHP
ASP.NET jQuery 实例9  通过控件hyperlink实现返回顶部效果
2012/02/03 Javascript
别了 JavaScript中的isXX系列
2012/08/01 Javascript
js 中的switch表达式使用示例
2020/06/03 Javascript
Js实现网页键盘控制翻页的方法
2014/10/30 Javascript
JS中处理时间之setUTCMinutes()方法的使用
2015/06/12 Javascript
jQuery中bind(),live(),delegate(),on()绑定事件方法实例详解
2016/01/19 Javascript
判断数组是否包含某个元素的js函数实现方法
2016/05/19 Javascript
jQuery实现的选择商品飞入文本框动画效果完整实例
2016/08/10 Javascript
基于bootstrap风格的弹框插件
2016/12/28 Javascript
jQuery插件FusionCharts绘制ScrollColumn2D图效果示例【附demo源码下载】
2017/03/22 jQuery
详解webpack 多页面/入口支持&公共组件单独打包
2017/06/29 Javascript
JavaScript中变量提升与函数提升经典实例分析
2018/07/26 Javascript
NodeJs之word文件生成与解析的实现代码
2019/04/01 NodeJs
vue.js实现左边导航切换右边内容
2019/10/21 Javascript
node.js使用http模块创建服务器和客户端完整示例
2020/02/10 Javascript
JavaScript 引用类型实例详解【数组、对象、严格模式等】
2020/05/13 Javascript
[03:48]2014DOTA2 TI专访71DK夺冠不靠小组赛高排名
2014/07/11 DOTA
浅谈Python的list中的选取范围
2018/11/12 Python
Python利用requests模块下载图片实例代码
2019/08/12 Python
django框架F&Q 聚合与分组操作示例
2019/12/12 Python
纪伊国屋泰国网上书店:Kinokuniya泰国
2017/12/24 全球购物
财务管理专业毕业生求职信范文
2013/09/21 职场文书
思想政治自我鉴定
2013/10/06 职场文书
《画风》教学反思
2014/04/16 职场文书
学雷锋标兵事迹材料
2014/08/18 职场文书
四风查摆问题自查报告
2014/10/10 职场文书
大学生个人学年总结
2015/02/15 职场文书
庆七一活动简报
2015/07/20 职场文书
详解CocosCreator项目结构机制
2021/04/14 Javascript
python分分钟绘制精美地图海报
2022/02/15 Python
Redis全局ID生成器的实现
2022/06/05 Redis