濟(jì)南網(wǎng)站建設(shè)函數(shù)式編程是編程范式的胡子時髦。 本來退居計(jì)算機(jī)科學(xué)學(xué)術(shù)界的史冊,函數(shù)式編程已經(jīng)有了近復(fù)興的主要是因?yàn)槠湓诜植际较到y(tǒng)實(shí)用工具(可能也因?yàn)椤凹兇狻钡墓δ苄哉Z言,如Haskell中是很難把握,這給他們帶來了一定的聲望)。
嚴(yán)格的函數(shù)式編程語言通常用于當(dāng)一個系統(tǒng)的性能和完整性都是重要的 – 即你的程序需要做的正是你期望每一次,需要在它的任務(wù)可以在數(shù)百聯(lián)網(wǎng)計(jì)算機(jī)或數(shù)千間共享的環(huán)境中運(yùn)行。 Clojure的 ,例如,權(quán)力Akamai的 ,海量內(nèi)容分發(fā)網(wǎng)絡(luò)通過如Facebook公司使用,而Twitter的著名采用 斯卡拉 ,其大多數(shù)性能密集型的零部件,并哈斯克爾 是其網(wǎng)絡(luò)安全系統(tǒng)中使用由AT&T。
這些語言對最前端的Web開發(fā)人員一個陡峭的學(xué)習(xí)曲線; 然而,許多更平易近人的語言把函數(shù)式編程,最值得注意的是Python的,無論是在其核心庫,與像功能特點(diǎn)map
和reduce
(我們將在一個有點(diǎn)談),并與諸如圖書館Fn.py ,隨著JavaScript中,使用再次收集方法,還與諸如圖書館Underscore.js 和Bacon.js 。
函數(shù)式編程可以是艱巨的,但請記住,它不僅是博士,數(shù)據(jù)科學(xué)家和宇航員的架構(gòu)。 對于大多數(shù)人來說,采用功能性風(fēng)格的真正好處是,我們的程序可以被分解成更小的,更簡單的片段,都更可靠,更容易理解。 如果你是一個前端開發(fā)人員使用數(shù)據(jù),特別是如果你使用的是D3,拉斐爾等的格式化的數(shù)據(jù)進(jìn)行可視化,那么函數(shù)式編程將在您的阿森納必備武器。
查找函數(shù)式編程的一個一致的定義是艱難的,而大多數(shù)文獻(xiàn)都依賴像有些預(yù)感報表“函數(shù)作為第一類對象”,并以防萬一“消除副作用?!辈粡澢愕拇竽X進(jìn)入海里,在更多的理論水平,函數(shù)式編程中經(jīng)常來解釋lambda演算 (有些實(shí)際上認(rèn)為 是函數(shù)式編程的基本數(shù)學(xué)) -但你可以放松。 從更實(shí)際的角度來看,初學(xué)者需要了解,以將其用于日常應(yīng)用(無需積分?。┲挥袃蓚€概念。
首先,在功能程序的數(shù)據(jù)應(yīng)該是一成不變的 ,這聽起來嚴(yán)重,但只是意味著它應(yīng)該永遠(yuǎn)不會改變。 起初,這可能看上去很奇怪(畢竟,誰需要一個程序,它永遠(yuǎn)不會改變什么嗎?),但在實(shí)踐中,你會簡單地創(chuàng)建,而不是修改那些已經(jīng)存在的新的數(shù)據(jù)結(jié)構(gòu)。 例如,如果你需要處理陣列中的一些數(shù)據(jù),那么你會成為一個新的數(shù)組與更新的值,而不是修改原始數(shù)組。 簡單!
其次,功能的程序應(yīng)該是無狀態(tài)的 ,這基本上意味著他們應(yīng)該執(zhí)行每一項(xiàng)任務(wù),仿佛是第一次,沒有知識,什么可能會或可能不會有先前在程序的執(zhí)行發(fā)生(你可能會說,一個無狀態(tài)的程序是無知的在過去的 )。 結(jié)合不變性,這可以幫助我們把每個功能就好像它是在真空中運(yùn)行,幸福無知的任何東西,除了在其他功能的應(yīng)用程序。 更具體而言,這意味著你的功能將在作為參數(shù)傳遞的數(shù)據(jù)只能操作,絕不會依靠外部值來執(zhí)行他們的計(jì)算。
不變性和無國籍的核心函數(shù)式編程,而且重要的是理解的,但如果他們不很有道理但不要擔(dān)心。 你會很熟悉這些原則由文章的最后,我答應(yīng)函數(shù)式編程之美,精度和功耗會變成你的應(yīng)用程序變成鮮艷,有光澤,數(shù)據(jù)極其糾結(jié)的彩虹。 現(xiàn)在,先從簡單的函數(shù)返回?cái)?shù)據(jù)(或其他功能),然后再結(jié)合這些基本構(gòu)建塊來執(zhí)行更復(fù)雜的任務(wù)。
例如,假設(shè)我們有一個API響應(yīng):
var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] } { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] } ];
如果我們想用一個圖表或圖形庫的平均溫度比較的人口規(guī)模,我們就需要編寫一些JavaScript代碼,做了一些更改數(shù)據(jù)之前,它的正確格式化為我們的可視化。 我們的圖形庫希望x和y坐標(biāo)的數(shù)組,如下所示:
[ [x, y], [x, y] …etc ]
這里, x
是平均溫度,并y
是種群規(guī)模。
如果沒有函數(shù)式編程(使用或不使用所謂的一個“勢在必行”的風(fēng)格),我們的程序可能看起來像這樣:
var coords = [], totalTemperature = 0, averageTemperature = 0; for (var i=0; i < data.length; i++) { totalTemperature = 0; for (var j=0; j < data[i].temperatures.length; j++) { totalTemperature += data[i].temperatures[j]; } averageTemperature = totalTemperature / data[i].temperatures.length; coords.push([averageTemperature, data[i].population]); }
即使是在一個人為的例子,這已經(jīng)成為難以遵循。 讓我們來看看我們可以做的更好。
當(dāng)在函數(shù)式風(fēng)格的編程,你一直在尋找可以抽象到一個功能簡單的,可重復(fù)的動作。 更多關(guān)于在第二個 – 然后,我們可以通過調(diào)用序列這些函數(shù)(也被稱為“創(chuàng)作”功能)構(gòu)建更復(fù)雜的功能。 與此同時,讓我們來看看,我們會采取在改造初期的API響應(yīng)我們的可視化庫所需的結(jié)構(gòu)過程中的步驟。 在一個基本的層面上,我們將執(zhí)行我們的數(shù)據(jù)執(zhí)行以下操作:
- 添加在列表中的每一個數(shù)字,
- 計(jì)算平均值,
- 從對象列表中檢索單個屬性。
我們將編寫一個函數(shù)為每個這三個基本動作,然后從這些功能組成我們的節(jié)目。 函數(shù)式編程可以是一個有點(diǎn)混亂在第一,你可能會受到誘惑而陷入舊勢在必行習(xí)慣。 為了避免這種情況,這里有一些簡單的基本規(guī)則,以確保您遵循以下最佳實(shí)踐:
- 所有的函數(shù)都必須接受至少一個參數(shù)。
- 所有的函數(shù)必須返回的數(shù)據(jù)或其他功能。
- 沒有循環(huán)!
好吧,讓我們添加在列表中的每個數(shù)字。 記住的規(guī)則,讓我們確保我們的函數(shù)接受一個參數(shù)(數(shù)字?jǐn)?shù)組添加),并返回一些數(shù)據(jù)。
function totalForArray(arr) { // add everything return total; }
到目前為止,一切都很好。 但我們?nèi)绾蝸碓L問每個項(xiàng)目在列表中,如果我們不這樣做循環(huán)過來的嗎? 問好你的新朋友,遞歸! 這是一個有點(diǎn)棘手,但基本上,當(dāng)你使用遞歸,您將創(chuàng)建一個函數(shù)調(diào)用自身,除非特定的條件已經(jīng)得到滿足 – 在這種情況下,返回一個值。 只是在看一個例子可能是最簡單的:
// Notice we're accepting two values, the list and the current total function totalForArray(currentTotal, arr) { currentTotal += arr[0]; // Note to experienced JavaScript programmers, I'm not using Array.shift on // purpose because we're treating arrays as if they are immutable. var remainingList = arr.slice(1); // This function calls itself with the remainder of the list, and the // current value of the currentTotal variable if(remainingList.length > 0) { return totalForArray(currentTotal, remainingList); } // Unless of course the list is empty, in which case we can just return // the currentTotal value. else { return currentTotal; } }
要注意的是:遞歸會讓你的程序更易讀,而且是必不可少的一個功能編程風(fēng)格。 然而,在一些語言(包括JavaScript),你會碰到問題時,你的程序使得大量的單次操作的遞歸調(diào)用(在撰寫本文時,“大”是關(guān)于10000鉻,50,000在Firefox中調(diào)用而在Node.js的11,000 )。 的細(xì)節(jié)超出了本文的范圍,但其要旨是,至少直到6 ECMAScript的釋放 ,JavaScript不支持所謂的“ 尾遞歸 “,這是遞歸的一種更有效的形式。 這是一個高級的話題,不會拿出很多時候,但它是值得了解的。
有了這樣的方式,請記住,我們需要來計(jì)算溫度的數(shù)組,以便然后計(jì)算平均的總溫度。 現(xiàn)在,而不是在遍歷每個項(xiàng)目temperatures
陣,我們可以簡單地這樣寫:
var totalTemp = totalForArray(0, temperatures);
如果你是純粹的,你可能會說,我們的totalForArray
功能可以進(jìn)一步細(xì)分。 例如,將兩個數(shù)相加的任務(wù)可能就會出現(xiàn)在您的應(yīng)用程序的其他部分,其后應(yīng)該真正將自己的功能。
function addNumbers(a, b) { return a + b; }
現(xiàn)在,我們的totalForArray
函數(shù)看起來像這樣:
function totalForArray(currentTotal, arr) { currentTotal = addNumbers(currentTotal, arr[0]); var remainingArr = arr.slice(1); if(remainingArr.length > 0) { return totalForArray(currentTotal, remainingArr); } else { return currentTotal; } }
優(yōu)秀的! 從數(shù)組中返回一個值是相當(dāng)常見于函數(shù)式編程,以至于它有一個特別的名字,“減量化”,這你會更常聽到的一個動詞,就像當(dāng)你“減少數(shù)組的單個值“JavaScript有一個特殊的方法只是為了執(zhí)行這一共同任務(wù)。 Mozilla開發(fā)者網(wǎng)絡(luò)提供了一個完整的解釋 ,但我們的目的很簡單,只要這樣:
// The reduce method takes a function as its first argument, and that function // accepts both the current item in the list and the current total result from // whatever calculation you're performing. var totalTemp = temperatures.reduce(function(previousValue, currentValue){ // After this calculation is returned, the next currentValue will be // previousValue + currentValue, and the next previousValue will be the // next item in the array. return previousValue + currentValue; });
但是,嘿,既然我們已經(jīng)定義了一個addNumber
功能,我們就可以使用它。
var totalTemp = temperatures.reduce(addNumbers);
事實(shí)上,由于總額高達(dá)數(shù)組是太酷了,讓我們把它列入自己的功能,使我們可以再次使用它,而不必記住所有的關(guān)于減少和遞歸的混亂的東西。
function totalForArray(arr) { return arr.reduce(addNumbers); } var totalTemp = totalForArray(temperatures);
啊,現(xiàn)在就是一些可讀的代碼! 只要你知道,方法,例如reduce
是常見的大多數(shù)函數(shù)式編程語言。 執(zhí)行上,以代替循環(huán)數(shù)組操作這些輔助方法通常被稱為“高階函數(shù)”。
繼續(xù)向前,我們列出的第二項(xiàng)任務(wù)是計(jì)算平均值。 這是很容易的。
function average(total, count) { return total / count; }
怎么可能,我們?nèi)カ@得平均為整個數(shù)組?
function averageForArray(arr) { return average(totalForArray(arr), arr.length); } var averageTemp = averageForArray(temperatures);
希望你已經(jīng)開始看到如何結(jié)合函數(shù)來執(zhí)行更復(fù)雜的任務(wù)。 這是可能的,因?yàn)槲覀兿旅孑d于本文章開頭的規(guī)則 – 即,我們的職能必須始終接受參數(shù)并返回?cái)?shù)據(jù)。 相當(dāng)真棒。
最后,我們想從對象的數(shù)組中檢索單個屬性。 而不是顯示你遞歸的更多示例中,我將切入正題和線索,你在另一個內(nèi)置的JavaScript方法: 圖 。 這種方法是當(dāng)你有一個結(jié)構(gòu)的數(shù)組,并需要將其映射到另一個結(jié)構(gòu),像這樣的:
// The map method takes a single argument, the current item in the list. Check // out the link above for more complete examples. var allTemperatures = data.map(function(item) { return item.temperatures; });
這很酷,但是從對象的集合拉一個單一的財(cái)產(chǎn)是你會做所有的時間,所以讓我們只為一個函數(shù)。
// Pass in the name of the property that you'd like to retrieve function getItem(propertyName) { // Return a function that retrieves that item, but don't execute the function. // We'll leave that up to the method that is taking action on items in our // array. return function(item) { return item[propertyName]; } }
檢查出來:我們已經(jīng)做了一個函數(shù),返回一個函數(shù)! 現(xiàn)在,我們可以把它傳遞給map
這樣的方法:
var temperatures = data.map(getItem('temperature'));
如果你喜歡的細(xì)節(jié),我們可以這樣做的原因是因?yàn)椋贘avaScript中,函數(shù)是“第一類對象”,這基本上意味著你可以通過周圍就像任何其他的價值功能。 而這是許多編程語言中的功能,它是可以在功能樣式可以使用任何語言的要求。 順便說一句,這也是你可以做的東西像的原因$('#my-element').on('click', function(e) … )
在第二個參數(shù)on
方法是一個function
,而當(dāng)你將函數(shù)作為參數(shù),你使用它們,就像你在命令式語言中使用的值。 整齊漂亮。
最后,讓我們換調(diào)用map
在它自己的功能,使事情變得更加易讀。
function pluck(arr, propertyName) { return arr.map(getItem(propertyName)); } var allTemperatures = pluck(data, 'temperatures');
好了,現(xiàn)在我們有,我們可以在我們的應(yīng)用程序在任何地方使用的通用功能的工具包,甚至在其他的項(xiàng)目。 我們可以從中總結(jié)的項(xiàng)目在一個數(shù)組,得到一個數(shù)組的平均值,并通過從對象列表采摘性質(zhì)作出新的陣列。 最后但并非最不重要的,讓我們回到我們最初的問題:
var data = [ { name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, … ];
我們需要改變像上面一成數(shù)組對象的數(shù)組x, y
對,是這樣的:
[ [75, 1000000], … ];
這里, x
是平均溫度,并y
為總?cè)丝凇?首先,讓我們找出我們所需要的數(shù)據(jù)。
var populations = pluck(data, 'population'); var allTemperatures = pluck(data, 'temperatures');
現(xiàn)在,讓我們把平均的數(shù)組。 請記住,我們傳遞給函數(shù)map
將被要求在陣列中的每個項(xiàng)目; 所以,該傳遞函數(shù)的返回值將被添加到一個新的數(shù)組,而新的數(shù)組最終將被分配給了averageTemps
變量。
var averageTemps = allTemperatures.map(averageForArray);
到目前為止,一切都很好。 但現(xiàn)在我們有兩個數(shù)組:
// populations [2047, 3568, 1000000] // averageTemps [55.25, 5.5, 75]
顯然,我們只想要一個陣列,所以讓我們寫一個函數(shù)來組合它們。 我們的函數(shù)應(yīng)該確保在索引中的項(xiàng)目0
的第一個陣列中的被配對的項(xiàng)在索引0
索引的第二陣列中,依此類推1
至n
(其中n
是項(xiàng)目的陣列中的總數(shù))。
function combineArrays(arr1, arr2, finalArr) { // Just so we don't have to remember to pass an empty array as the third // argument when calling this function, we'll set a default. finalArr = finalArr || []; // Push the current element in each array into what we'll eventually return finalArr.push([arr1[0], arr2[0]]); var remainingArr1 = arr1.slice(1), remainingArr2 = arr2.slice(1); // If both arrays are empty, then we're done if(remainingArr1.length === 0 && remainingArr2.length === 0) { return finalArr; } else { // Recursion! return combineArrays(remainingArr1, remainingArr2, finalArr); } }; var processed = combineArrays(averageTemps, populations);
或者,因?yàn)閱涡械臉啡ぃ?/p>
var processed = combineArrays(pluck(data, 'temperatures').map(averageForArray), pluck(data, 'population')); // [ // [ 55.25, 2047 ], // [ 5.5, 3568 ], // [ 75, 1000000 ] // ]
讓我們真正的
最后但并非最不重要的,讓我們再看一個真實(shí)世界的例子,這一次增加了我們與功能toolbelt Underscore.js ,它提供了許多偉大的函數(shù)式編程助手一個JavaScript庫。 我們將從沖突和災(zāi)難的信息,我一直在努力名為在一個平臺上提取數(shù)據(jù)CrisisNET ,我們將用夢幻般的D3 庫以可視化的數(shù)據(jù)。
我們的目標(biāo)是讓人們來CrisisNET的主頁的信息系統(tǒng)類型的快照。 為了證明這一點(diǎn),我們可以從分配給一個特定的類別,如“身體暴力”或“武裝沖突”。這樣的API計(jì)算文件的數(shù)量,用戶可以看到他們找到了話題多的信息是如何使用最有趣的。
氣泡圖可能是一個不錯的選擇,因?yàn)樗鼈兘?jīng)常被用來代表一大群人的相對大小。 幸運(yùn)的是,D3有一個內(nèi)置的可視化命名的pack
僅此目的。 所以,讓我們創(chuàng)建一個圖形pack
,其中顯示一個給定的類的名稱將出現(xiàn)在從CrisisNET的API響應(yīng)的次數(shù)。
在我們繼續(xù)之前,請注意,D3是一個復(fù)雜的庫,保證其自身教程(或很多教程,對于這個問題)。 因?yàn)楸疚牡闹攸c(diǎn)是函數(shù)式編程,我們不會花很多時間在D3是如何工作的。 但不要擔(dān)心-如果你不熟悉圖書館,你應(yīng)該能夠復(fù)制并粘貼代碼片段具體到D3和深入細(xì)節(jié)另一個時間。 斯科特·穆雷的D3教程 是一個很好的資源,如果你“再有興趣學(xué)習(xí)更多。
順動,讓我們先來確保我們有一個DOM元素,讓D3有一些地方把圖表它將與我們的數(shù)據(jù)產(chǎn)生。
<div id="bubble-graph"></div>
現(xiàn)在,讓我們創(chuàng)建我們的圖表,并將其添加到DOM。
// width of chart var diameter = 960, format = d3.format(",d"), // creates an ordinal scale with 20 colors. See D3 docs for hex values color = d3.scale.category20c(), // chart object to which we'll be adding data var bubble = d3.layout.pack() .sort(null) .size([diameter, diameter]) .padding(1.5); // Add an SVG to the DOM that our pack object will use to draw the // visualization. var svg = d3.select("#bubble-graph").append("svg") .attr("width", diameter) .attr("height", diameter) .attr("class", "bubble");
該pack
對象采用對象的這種格式的數(shù)組:
{ children: [ { className: , package: "cluster", value: } ] }
CrisisNET的數(shù)據(jù)API將返回此格式的信息:
{ data: [ { summary: "Example summary", content: "Example content", … tags: [ { name: "physical-violence", confidence: 1 } ] } ] }
我們看到,每個文檔都有一個tags
屬性,該屬性包含的項(xiàng)目的數(shù)組。 每個標(biāo)簽項(xiàng)都有一個name
屬性,這就是我們所追求的。 我們需要找到在CrisisNET的API響應(yīng)每一個獨(dú)特的標(biāo)記名稱,數(shù)一數(shù)該標(biāo)簽的名字出現(xiàn)的次數(shù)。 讓我們先通過隔離,我們需要使用的信息pluck
我們前面創(chuàng)建的函數(shù)。
var tagArrays = pluck(data, 'tags');
這給了我們一個數(shù)組的數(shù)組,如下所示:
[ [ { name: "physical-violence", confidence: 1 } ], [ { name: "conflict", confidence: 1 } ] ]
但是,我們真正想要的是一個陣列,在它的每一個標(biāo)簽。 所以,讓我們使用來自Underscore.js一個方便的函數(shù)叫做拉平 。 這將需要的值從任何嵌套數(shù)組,給我們一個數(shù)組,它是一層。
var tags = _.flatten(tagArrays);
現(xiàn)在,我們的數(shù)組是一個比較容易處理:
[ { name: "physical-violence", confidence: 1 }, { name: "conflict", confidence: 1 } ]
我們可以用pluck
再次得到我們真正想要的東西,這是唯一的標(biāo)記名稱的簡單列表。
var tagNames = pluck(tags, 'name'); [ "physical-violence", "conflict" ]
啊,那最好不過了。
所以現(xiàn)在,我們來計(jì)算的次數(shù)相對簡單的任務(wù),每一個標(biāo)簽的名字出現(xiàn)在我們的名單,然后將這些名單到由D3所需要的結(jié)構(gòu)pack
,我們在前面創(chuàng)建的布局。 正如你可能已經(jīng)注意到,數(shù)組是一個非常流行的數(shù)據(jù)結(jié)構(gòu),函數(shù)式編程 – 大多數(shù)工具都設(shè)計(jì)時考慮到陣列。 作為第一步,接下來,我們將創(chuàng)建一個這樣的數(shù)組:
[ [ "physical-violence", 10 ], [ "conflict", 27 ] ]
在這里,數(shù)組中的每個項(xiàng)目都有索引標(biāo)簽名0
和索引標(biāo)簽的總計(jì)數(shù)1
。 我們只需要為每個唯一的標(biāo)記名稱的數(shù)組,所以讓我們開始創(chuàng)建,其中每個標(biāo)記名只出現(xiàn)一次的數(shù)組。 幸運(yùn)的是,Underscore.js方法的存在只是為了這個目的。
var tagNamesUnique = _.uniq(tagNames);
讓我們也擺脫任何false-y
false
, null
, ""
等)值使用另一個得心應(yīng)手Underscore.js功能。
tagNamesUnique = _.compact(tagNamesUnique);
從這里,我們可以寫一個函數(shù),使用另一個內(nèi)建的JavaScript收集方法,命名為我們生成數(shù)組過濾器 ,該過濾器根據(jù)條件的數(shù)組。
function makeArrayCount(keys, arr) { // for each of the unique tagNames return keys.map(function(key) { return [ key, // Find all the elements in the full list of tag names that match this key // and count the size of the returned array. arr.filter(function(item) { return item === key; }).length ] }); }
現(xiàn)在,我們可以很容易地創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu)pack
通過映射我們的陣列列表需要。
var packData = makeArrayCount(tagNamesUnique, tagNames).map(function(tagArray) { return { className: tagArray[0], package: "cluster", value: tagArray[1] } });
最后,我們可以在我們的數(shù)據(jù)傳遞到D3和產(chǎn)生在我們的SVG DOM節(jié)點(diǎn),一個圓圈為每一個獨(dú)特的標(biāo)記名稱,大小相對于總次數(shù)該標(biāo)簽的名字出現(xiàn)在CrisisNET的API響應(yīng)。
function setGraphData(data) { var node = svg.selectAll(".node") // Here's where we pass our data to the pack object. .data(bubble.nodes(data) .filter(function(d) { return !d.children; })) .enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); // Append a circle for each tag name. node.append("circle") .attr("r", function(d) { return dr; }) .style("fill", function(d) { return color(d.className); }); // Add a label to each circle, using the tag name as the label's text node.append("text") .attr("dy", ".3em") .style("text-anchor", "middle") .style("font-size", "10px") .text(function(d) { return d.className } ); }
全部放在一起,這里的setGraphData
和makeArray
在上下文中的功能,包括使用jQuery調(diào)用CrisisNET的API(你需要獲得一個API密鑰 )。 我也貼了GitHub上充分合作的例子 。
function processData(dataResponse) { var tagNames = pluck(_.flatten(pluck(dataResponse.data, 'tags')), 'name'); var tagNamesUnique = _.uniq(tagNames); var packData = makeArrayCount(tagNamesUnique, tagNames).map(function(tagArray) { return { className: tagArray[0], package: "cluster", value: tagArray[1] } }); return packData; } function updateGraph(dataResponse) { setGraphData(processData(dataResponse)); } var apikey = // Get an API key here: http://api.crisis.net var dataRequest = $.get('http://api.crisis.net/item?limit=100&apikey=' + apikey); dataRequest.done( updateGraph );
這是一個漂亮的深潛,所以與它堅(jiān)持的祝賀! 正如我所提到的,這些概念可以在第一是具有挑戰(zhàn)性的,但抵制誘惑,敲定for
循環(huán)為你的后半生。
在幾周內(nèi),使用函數(shù)式編程技術(shù),你會很快建立了一套簡單,可重復(fù)使用的功能,這將大大提高你的應(yīng)用程序的可讀性。 此外,您將能夠顯著更快地處理數(shù)據(jù)結(jié)構(gòu),淘汰曾經(jīng)被認(rèn)為是令人沮喪的調(diào)試中的幾行代碼30分鐘。 一旦你的數(shù)據(jù)已經(jīng)被正確地格式化,你會弄花更多的時間在有趣的部分:制作可視化看起來真棒!