微信号:gh_ffb279ea1674

介绍:《奇舞周刊》是由奇舞团维护的前端技术周刊.每周五向大家推送前端技术文章.

去其糟粕,取其精华——我如何重拾对 JavaScript 的爱

2017-08-12 21:28 众里寻他千百度

编者按:本文由众里寻他千百度在众成翻译平台上翻译。

Alexas拍摄

我与 JavaScript 的因缘

我的 JavaScript 之旅开始于1997年,那时我在使用网景公司的 Navigator 3 浏览器。在当时你无法使用 JavaScript 做很多事情。JavaScript 最炫酷的使用方式就是创建鼠标悬停事件。使用鼠标悬停来改变网页内容在当时可是一个高端技术。顺便说一句,那时还都只是 pre-DHTML,所以我们无法手动显示/隐藏 DOM 元素。

在那个年代,JavaScript 的发展是非常缓慢的,主要被用于表单验证。那时 JavaScript 没有太大进展,人们对它也没什么兴趣,与今天形成鲜明对比。它只是一个锦上添花的东西,你必须保证你的应用在禁用 JavaScript 的时候依然可以正常运行。

后来,大量的框架进入市场。如 jQuery,Knockout,Angular,React,Vue 等。一开始它们的出现速度比较慢,而现在我们经常能看到一个新的框架。

我们也看到了 JavaScript 自身改进速度的加快。我们一开始花了很长时间才得到了 ES6,随着迭代速度的加快,人们甚至已经停止讨论 ES7 开始研究 ES8 了。

我们也有很多 JavaScript 的衍生语言可以使用,例如 TypeScript, CoffeeScript,ClojureScript,ELM 等等。

这使得知识量变的巨大无比,我们不太可能同时学好所有东西。

走弯路

当 JavaScript 刚刚开始走向成熟,面向对象编程 (OOP) 开始渗透到这门语言…然后我爱上了它。

我开始尝试用各种方式用 JavaScript 创建一个类。最终,我能正确地使用继承。我这时开始认为,JavaScript 变成了一门真正的编程语言。

直到多年后我才发现在 JavaScript 中使用面向对象编程事一个严重的错误。

我尝试在 JavaScript 里使用我在 C# 里学到的东西,一开始这看起来很对,但是复杂度令人发指。

因为 JavaScript 的原型式继承不像 C# 那样,我发现我每天都在写console.log(this)(为了确定代码如何继承,现在是在父类还是子类)。如果你不能保证不出一点差错,这将是一场噩梦。私有方法和变量必须使用下划线开头,甚至要使用一些闭包来包装。

在 JavaScript 中使用面向对象编程,不仅存在 OOP 本身的问题,还产生了更多其它的问题。

后来我发现了函数式编程

一开始我没搞明白什么是函数式编程。我会去阅读代码并去理解代码,但是我还是不理解为什么这么做。最终,我强迫自己去学习它。我上了一门叫函数式编程入门的 EDX 的免费课程,并在 JavaScript 中应用学到的技术。

函数式编程给了我一个新的观点,它让我站在一个全新的视角审视编程。

一开始我对函数式编程感到奇怪,我花了很久才习惯它。所有东西都是不逆向的、可变的、陌生的。

慢慢地,我尝试用函数式的方式来写代码。因为我一开始不熟悉它,所以需花费了更多的时间去练习。最终我使用地越来越熟练,理解了函数式编程的内涵。

我的代码变得简单可复用。慢慢地,常见的语言特性开始从我的代码中消失。我的代码看起来像一个完全不同的语言。这还是我写的 JavaScript 吗?

弃用 ‘var’

所有 varconst 替换。当我的代码变得 不可改变的(immutable)并且使用了纯函数时, var 关键字完全消失了。

我查看我的代码惊叹于看不到一个 var 甚至 let,所有变量都用 const 声明时,我对 JavaScript 的兴趣不断提升。

‘for’ 循环

处理 for 循环是首先要做的事情之一。我开始把大多数的 for 循环替换为 filtermapreduce。 需要额外东西的 for 循环被递归和库替代 ,例如lazy.js。 在你要使用 break 这个关键词之前, 阅读这里.

重新思考 JavaScript: for 循环之死_JavaScript 的 for 循环发挥了巨大的价值,但是它现在变得过时,应当退休让位于函数式编程…_hackernoon.com

for 循环在我的代码已经消失。如果你在我的代码中看到的话,告诉我,我把它去掉。

‘if’ 声明

if 声明是接下来要讨论的事情。我停止在 if-else 声明里嵌套大量代码块(这也是面向对象编程的良好实践)。 逻辑被抽象到了函数里。在这之后,就显而易见地把 if 替换成简单易懂的三元表达式了。

重新思考 JavaScript: if 声明函数式的思维方式扩展了我编程的思想。让我对代码有了更深入的理解_hackernoon.com

在我的代码中看到 if 声明已经不太可能。为了提高代码的可读性,我会很少使用它。

放弃 ‘switch’

除了 iffor , 下一个我弃用的特征是 switch。虽然这个特征不太常用,我仍想使用函数式编程来替代它。

重新思考 JavaScript: 为了写出更好的代码而去除 switch 声明在我上面的三篇文章中,我劝你去除 for 循环、if 声明,不再使用 break。 接下来我将…hackernoon.com

我也很喜欢 Ramda 的 cond 操作符 来替代 switch.

不再使用 ‘this’

是的,你没听错。this 已经完全消失。如果在这点上你没有像我这样,现在你应该开始这样了。

函数式的 JavaScript 将会让你的整个程序不用出现 this

现在,代码里只有数据和函数,我们完全不需要 this。我开始将对象视为可变的状态+函数。我不需要把可变状态或函数附加到对象上,所以我把它们分离开了。

我甚至写了一篇文章讨论了把方法从对象中解耦的好处。

函数式的 JavaScript: 从对象中解耦方法_在我的项目中总是做的一件事就是把方法从对象中解耦。 map,filter,reduce…_hackernoon.com

面向对象的设计是没必要的

现在回过头来看,我意识到 OOP 增加了不必要的复杂度。我发现我可以在没有可变状态的情况下执行相同的任务。

代码变得更轻量了,因为我不再需要操作这些繁杂的对象了。代码里只有数据和函数。现在这些函数由于不再依赖于对象变得更加可复用。

我不再需要担心所有与继承有关的问题,因为这不是 JavaScript 所擅长的。

JavaScript 缺少私有、公共、内部或受保护的访问修饰符也不再是一个问题。创建访问修饰符是用来解决面向对象编程所引起的问题的。这些问题在函数式的 JavaScript 中不复存在。

总结

我的代码现在看起来完全不同。 它包含许多纯函数,并使用ES6 模块组织起来。我用这些函数来组成更复杂的函数。大部分函数是只有一行的 的 λ 表达式,它立即返回一个值。

我现在把软件输入视为数据流,然后基于这些数据流进行编程。

我对函数编程的理解使我有了更多的选择来解决常见问题。

我还学习到函数式编程是包容的 ,在现有项目中你可以根据需要或多或少地使用它。C# 的 LINQ 就是一个很好的在面向对象语言里使用函数式设计的例子。

函数式编程是很美好的。谢谢!


奇舞周刊

——————————————————

领略前端技术 阅读奇舞周刊


长按二维码,关注奇舞周刊


 
奇舞周刊 更多文章 奇舞周刊第 222 期:前端路上的旅行 这5个CSS属性你可能都不知道! JavaScript 疲劳终极指南:我们行业的真相 读《深入PostCSS Web设计》,参与活动赢新书! 使用font-display 定制字体渲染策略
猜您喜欢 “龙书”作者Jeffery Ullman:相信你自己,自由地思考 当我们谈 XML 布局文件代码的优雅性 玩转 Windows 10 中的 Linux 子系统 HA 高可用软件系统保养指南 2017跳槽旺季,大数据告诉你该怎么选