原文连接: http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-intro/;
原文做者: James Sinclair;javascript
这篇文章是介绍函数式编程的四篇文章中的第一篇。在这篇文章中,咱们来看一下让 JavaScript 成为适合函数式编程的组成部分,而且看看为何它将会是颇有用的。html
Part1 组成部分和动机,java
Part2 使用数组和列表,编程
Part3 生成函数的函数,数组
Part4 使用函数式编程的风格,ide
为何函数式 JavaScript 如此夸大其词呢?为何它叫作函数式?它不是像任何人去写一个功能失调或者没有函数式的 JavaScript。它的好处是什么?你的烦恼是什么?
对于我来说,学习函数式编程就像获得了一个多功能食品料理机同样:函数式编程
它的前提是须要一些学习成本函数
你能够告诉你的朋友和家人它是多么使人惊喜post
它们将会开始怀疑你是否是加入了某个异教团
可是,它确实让不少任务变得简单,它甚至能够自动处理一些在某些方面至关无聊和浪费时间的东西。学习
在咱们去思考这为何是个好主意以前,让咱们用 JavaScript 的一些基本特性去实现函数式编程。在 JavaScript 中,有两个关键的组成部分:变量和函数,变量就像一个容器,咱们能够把一些东西放在里面,就像这样:
var myContainer = "Hey everybody! Come see how good I look!";
上面的代码建立的一个容器,而且将一个字符串放在了里面。
在另外一方面,函数,它是一种途径能够绑定一些指令用于咱们能够再使用它,它还能让事情变得有条理,所以咱们不用一会儿去考虑每一件事情。咱们能够建立一个函数像这样:
function log(someVariable) { console.log(someVariable); return someVariable; }
咱们能够这样调用它:
log(myContainer); // Hey everybody! Come see how good I look!
当时,若是你以前了解过一些 JavaScript ,就会知道咱们还能够像下面这样编写和调用函数:
var log = function(someVariable) { console.log(someVariable); return someVariable; } log(myContainer); // Hey everybody! Come see how good I look!
让咱们仔细观察,当咱们用这种方式定义一个函数的时候,至关于咱们创造一个叫作 log
的变量,而后把一个函数赋值给它。事实也确实如此。咱们的 log()
函数是一个变量,这意味着咱们能够对他作和其余变量同样的事情。
让咱们试一试,或许咱们能够把一个函数做为一个参数传给另外一个函数:
var classyMessage = function() { return "Stay classy San Diego!"; } log(classyMessage); // [Function]
hahahaha,好像没什么有用的惊喜啊,让咱们尝试用不一样的方式:
var doSomething = function(thing) { thing(); } var sayBigDeal = function() { var message = "I’m kind of a big deal"; log(message); } doSomething(sayBigDeal); // I’m kind of a big deal
这应该不会让你感到很是激动,当时它让那些计算机科学家很是地激动。它可以把函数放在一个变量中,有时候能够这么说“函数是 JavaScript 中的第一类对象”。这意味着处理对待函数和其余的数据类型就像对象或者字符串没什么两样。而且这一个小的特性将会惊人地有用,为了搞明白为何,咱们得谈一谈 DRY 原则。
程序猿喜欢说 DRY 原则 ———— 不要重复你本身,它的意思是说,若是你须要去屡次执行一样的任务,把它们绑定在一类能够重复使用的包里面(就像函数),这样的话,若是你想要调整任务设置的话,你只需在一个地方改动就好了——函数。
让咱们看看这个例子,咱们使用一个轮播库在页面上放三个轮播组件:
var el1 = document.getElementById('main-carousel'); var slider1 = new Carousel(el1, 3000); slider1.init(); var el2 = document.getElementById('news-carousel'); var slider2 = new Carousel(el2, 5000); slider2.init(); var el3 = document.getElementById('events-carousel'); var slider3 = new Carousel(el3, 7000); slider3.init();
上面的代码有些重复,咱们想要给页面上的元素初始化一个轮播组件,而且每一个都带有一个特定的 ID ,让咱们看看如何在函数中去初始化一个轮播组件,而后给每一个 ID 调用这个函数。
function initialiseCarousel(id, frequency) { var el = document.getElementById(id); var slider = new Carousel(el, frequency); slider.init(); return slider; } initialiseCarousel('main-carousel', 3000); initialiseCarousel('news-carousel', 5000); initialiseCarousel('events-carousel', 7000);
这样,代码就很是简洁了而且很好去维护。咱们能够遵循下面一个准则:当咱们须要对不一样的数据作一系列相同的操做的时候,咱们能够把这些操做包装在一个函数中。当是若是这些操做也存在一些不一样呢?
var unicornEl = document.getElementById('unicorn'); unicornEl.className += ' magic'; spin(unicornEl); var fairyEl = document.getElementById('fairy'); fairyEl.className += ' magic'; sparkle(fairyEl); var kittenEl = document.getElementById('kitten'); kittenEl.className += ' magic'; rainbowTrail(kittenEl);
去重构这些代码有些复杂,它确实是一个重复的模式,可是咱们给每一个元素调用了不一样的函数,咱们能够第一步先包装 document.getElementById()
的调用和添加 className
的操做到一个函数,这样能够下降一些重复度:
function addMagicClass(id) { var element = document.getElementById(id); element.className += ' magic'; return element; } var unicornEl = addMagicClass('unicorn'); spin(unicornEl); var fairyEl = addMagicClass('fairy'); sparkle(fairyEl); var kittenEl = addMagicClass('kitten'); rainbow(kittenEl);
可是咱们怎样让他变得更 DRY 一些呢?若是你记得 JavaScript 能够容许咱们把一个函数做为一个参数传给另外一个函数:
function addMagic(id, effect) { var element = document.getElementById(id); element.className += ' magic'; effect(element); } addMagic('unicorn', spin); addMagic('fairy', sparkle); addMagic('kitten', rainbow);
这变得更简洁了,而且更易于维护,这种把函数座位参数传递的能力是咱们看到了更多的可能性,在下一节咱们将会看到如何使用这种能力是数组变得更友好。
未亡待续...
阅读下一节~
原文来自个人博客 http://qiutc.me/post/a-gentle-introduction-to-functional-javascript-part-1.html欢迎你们关注~