国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Javascript函數式編程簡單介紹

2019-11-20 11:28:42
字體:
來源:轉載
供稿:網友

幾十年來,函數式編程一直是計算機科學狂熱者的至愛,由于數學的純潔性和謎一般的本質, 它被埋藏在計算機實驗室,只有數據學家和有希望獲得博士學位的人士使用。但是現在,它正經歷一場復興, 這要感謝一些現代語言比如Python,Julia,Ruby,Clojure以及――但不是最后一個――Javascript。

你是說Javascript?這個WEB腳本語言?沒錯!

Javascript已經被證明是一項長期以來都沒有消失的重要的技術。這主要是由于它擴展的一些框架和庫而使其具有重生的能力, 比如backbone.js,jQuery,Dojo,underscore.js等等。這與Javascript函數式編程語言的真實身份直接相關。 對Javascript函數式編程的理解很重要,并且在相當長的一段時間會對各種水平的程序員很有用。

為什么呢?函數式編程非常強大、健壯并且優雅。它對于大型數據結構非常有用并且高效。 Javascript作為一個客戶端腳本語言,在應對日益復雜的網站時,函數式地操作DOM、 組織API響應以及完成一些其它任務會非常有好處。

在這本書里,你將會學習用Javascript進行函數式編程所需要知道的一切:如何用函數式編程構建你的Javascript web應用, 如何解鎖Javascript隱藏的力量,如何編寫更強大的代碼,并且由于程序更小,使得代碼更容易維護,能夠更快被下載, 并且花費更少的開支。你還會學到函數式編程的核心概念,以及如何將它們應用到Javascript, 還有將Javascript作為函數式語言時如何回避一些問題,如何在Javascript中混合使用函數式編程和面向對象編程。

不過在我們開始前,先來做個實驗。

例子

也許快速舉個例子是介紹Javascript函數式編程最好的方式。我們將用Javascript完成一些任務―― 一個使用傳統、原生的方法,另一個使用函數式編程。然后我們將會比較這兩種方法。

應用――一個電子商務網站

為了追求真實感,我們來做一個電子商務網站,一個郵購咖啡豆的公司。這個網站會銷售好幾種類型的咖啡, 有不同的品質,當然也有不同的價格。

命令式方法

首先,我們開始寫程序。為了讓這個例子接地氣,我們需要創建一些對象來保存數據。如果需要的話我們可以從數據庫里取值。 但是現在我們假設他們是靜態定義的: 

 // create some objects to store the data.var columbian = { name: 'columbian', basePrice: 5};var frenchRoast = { name: 'french roast', basePrice: 8};var decaf = { name: 'decaf', basePrice: 6};// 我們將使用輔助函數計算價格// 根據size打印到一個HTML的列表中function printPrice(coffee, size) { if (size == 'small') {  var price = coffee.basePrice + 2; } else if (size == 'medium') {  var price = coffee.basePrice + 4; } else {  var price = coffee.basePrice + 6; } // create the new html list item var node = document.createElement("li"); var label = coffee.name + ' ' + size; var textnode = document.createTextNode(label+' price: $'+price); node.appendChild(textnode); document.getElementById('products').appendChild(node);}// 現在我們只需根據咖啡的各種價格和size的組合調用printPrice函數printPrice(columbian, 'small');printPrice(columbian, 'medium');printPrice(columbian, 'large');printPrice(frenchRoast, 'small');printPrice(frenchRoast, 'medium');printPrice(frenchRoast, 'large');printPrice(decaf, 'small');printPrice(decaf, 'medium');printPrice(decaf, 'large');

如你所見,這個代碼非常基礎。如果現在有更多的咖啡種類而不只是這三個改怎么辦?如果有20個,甚至50個? 如果有更多的size呢?如果有有機和無機之分呢?這將會很快將代碼量變得巨大無比!

采用這種方法,我們讓機器去打印每一種咖啡類型和每一個size。這就是采用這種命令式方法的基本問題。

函數式編程

命令式的代碼一步一步地告訴電腦需要做什么來解決問題,相反,函數式編程追求用數學方式來描述問題, 其余的交給電腦來做。

通過更函數式一些的方式,同樣的應用可以這樣來寫:

// 從接口中分解數據和邏輯var printPrice = function(price, label) { var node = document.createElement("li"); var textnode = document.createTextNode(label+' price: $'+price); node.appendChild(textnode); document.getElementById('products 2').appendChild(node);}// 為每種咖啡創建函數對象var columbian = function(){ this.name = 'columbian'; this.basePrice = 5;};var frenchRoast = function(){ this.name = 'french roast'; this.basePrice = 8;};var decaf = function(){ this.name = 'decaf'; this.basePrice = 6;};// 為每種size通過字面量創建對象var small = { getPrice: function(){return this.basePrice + 2}, getLabel: function(){return this.name + ' small'}};var medium = { getPrice: function(){return this.basePrice + 4}, getLabel: function(){return this.name + ' medium'}};var large = { getPrice: function(){return this.basePrice + 6}, getLabel: function(){return this.name + ' large'}};// 將所有咖啡的種類和size放到數組里var coffeeTypes = [columbian, frenchRoast, decaf];var coffeeSizes = [small, medium, large];// 創建由上面內容組成的新對象,并把它們放到一個新數組里var coffees = coffeeTypes.reduce(function(previous, current) { var newCoffee = coffeeSizes.map(function(mixin) {  // `plusmix`是函數式的minxin, 見第7章  var newCoffeeObj = plusMixin(current, mixin);  return new newCoffeeObj(); }); return previous.concat(newCoffee);},[]);// 現在我們已經定義了如何獲得所有咖啡種類和size組合方式的價格,現在可以直接打印它們了coffees.forEach(function(coffee){ printPrice(coffee.getPrice(),coffee.getLabel());});

首先需要明確的是這個代碼更加模塊化了。現在新增一種size或者信新增一個咖啡種類就像下面的代碼這樣簡單:

var peruvian = function(){ this.name = 'peruvian'; this.basePrice = 11;};var extraLarge = { getPrice: function(){return this.basePrice + 10}, getLabel: function(){return this.name + ' extra large'}};coffeeTypes.push(Peruvian);coffeeSizes.push(extraLarge);

咖啡對象的數組和size對象的數組混合(mix)到了一起,也就是他們的方法和成員變量被組合到了一塊兒 ――通過一個叫“plusMinxin”的自定義函數(詳見第七章)。這些咖啡類型的類(columbian, frenchRoast, decaf)包含了成員變量, 而這些size對象(small, medium, large)包含了獲取名稱和計算價格的方法。 ”混合”(minxing)這個動作通過一個map操作來起作用,也就是對數組中的每一個成員執行一個純函數并返回一個新的函數, 然后這些返回的函數被放到了一個reduce函數中被操作,reduce也是一個高階函數,和map有些像, 只是reduce把數組里的所有元素處理后組合到了一個東西里面。最終,新的數組包含了所有可能的種類和size的組合, 這個數組通過forEach方法遍歷,forEach也是一個高階函數,它會讓數組里面每一個對象作為參數執行一遍回調函數。 在這個例子里,這個回調函數是一個匿名函數,它獲取這些對象后,以對象的getPrice()和getLabel() 兩個方法的返回值作為參數調用printPrice函數。

實際上,我們可以讓這個例子更加函數式:去掉coffees變量,并將函數串到一起鏈式調用,這也是函數式編程的一個小技巧。

coffeeTypes.reduce(function(previous, current) { var newCoffee = coffeeSizes.map(function(mixin) {  // `plusMixin` function for functional mixins, see Ch.7  var newCoffeeObj = plusMixin(current, mixin);  return new newCoffeeObj(); }); return previous.concat(newCoffee);},[]).forEach(function(coffee) { printPrice(coffee.getPrice(),coffee.getLabel());});

這樣,控制流沒有像命令式代碼那樣從頭到尾的順序進行。在函數式編程里,map函數和其它高階函數代替了for和while循環, 只有少量關鍵的代碼是在順序執行。 這使得新接觸的人在閱讀這樣范式的代碼有些困難,但是一旦你能夠欣賞它,你就會發現這根本沒啥難的, 而且這樣寫看起來更好。

這個例子僅僅是剛開始展露Javascript中函數式編程能做什么。通過這本書,你將會看到更多函數式實現的強悍的例子。

總結

首先,采用函數式風格的優點已經明確了。 其次,不要害怕函數式編程。的確,它往往被認為是編程語言的純邏輯形式,但是我們不需要理解lambda演算也能夠在日常任務中應用它。 實際上,通過把我們的程序拆分成小的片段,它們變得更容易被理解、維護,也更加可靠。 map和reduce函數是Javascript中不太被知道的內建函數,然而我們將要關注它們。

Javascript是一個腳本語言,可交互,易使用,不需要編譯。我們甚至不需要下載任何開發軟件, 你最喜歡的瀏覽器就可以作為開發環境的解釋器。

感興趣嗎?好,我們開始!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 会泽县| 治县。| 洪湖市| 武定县| 兴仁县| 沛县| 梅州市| 会东县| 丹巴县| 新乐市| 德兴市| 凯里市| 集安市| 长春市| 丹东市| 广东省| 克东县| 中西区| 衡东县| 康平县| 房产| 沙河市| 刚察县| 高唐县| 新绛县| 乐业县| 内丘县| 全南县| 灵山县| 荃湾区| 霞浦县| 通化市| 仙居县| 高邮市| 泰宁县| 灵丘县| 岚皋县| 长寿区| 苏尼特左旗| 西平县| 景泰县|