原文連接: 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歡迎你們關注~