高階函數與JavaScript

來源:互聯網
上載者:User

簡單的JavaScript?
Web語言JavaScript的原意被很多人曲解了,絕大部分的人(包括以前我在做項目的時候)其實都沒有正確地使用 HTML 和 CSS。幾乎沒有人是通過FP的特性規範來學習JavaScript的,他們都是通過流行的OO設計教材和閱讀以前遺留的代碼來學習的。很遺憾的是OO這兩種學習途徑對於他們真正理解 JavaScript理念都沒有多少協助,甚至還存在著大量的誤導。比如在編碼中仍未擺脫大量的過程式編程,或著更“進階一點”,大量使用偽類來做架構。他們不知道這些東西自從應用了函數式JS後全部都是過時了的方法。這是不是JavaScript本身的罪過?我並不這樣認為。越是簡單的東西越容易被誤用(當然簡單並不意味它不好,不能協助你完成工作)。有多少
Web 設計教材宣稱你只需要三天就可以精通JavaScript,真實情況當然並不是這樣。

高階函數(Higher Order Function)作為函數式編程眾多風格中的一項顯著特徵,經常被使用著。按照維基百科上面的定義,高階函數是至少滿足下列一個條件的函數:

  • 接受函數作為輸入
  • 輸出一個函數

咱們比較難真正地理解這兩句話?那不妨詳細地解釋一下。在函數式語言中,函數不但是一種特殊的對象,而且還是第一等的“公民”,可以把函數作為一種“類型”,因此函數本身是一個可以傳來傳去的“值”。也就是說,某個一個函數剛開始執行的時候,總可以送入一個“函數的參數”。參數傳入了,它本身就是一個函數。當然,這時候的這個輸入的函數是相當於“某一個函數”的“另外一個函數”。好了,當函數執行完畢之後,您又可以返回“另外一個新的函數”,取決於您return fn(){...}的是什麼。於是最後,上述出現三個不同的函數,分別有不同的角色。要達到這樣的話,不把函數是作為一個“值”,是不能夠實現的。

我們知道,JavaScript是一門靈活的語言,而且是一門精巧的函數式語言。下面就通過JavaScript來實踐一下高階函數。首先是“函數作為參數”的示範,在瀏覽器中執行

例子一:document.write([2,3,1,4].sort()); // 列印"1,2,3,4"

這是最簡單不過的數組排序語句了。實際上Array.prototype.sort()還能夠支援一個可選的參數“比較函數”,其形式如sort(fn),fn是一個函數類型(Function)的值,說明了這裡就應用到函數式編程的“高階函數”。我們看看例子二,這是一個對日期類型排序的sort()。

例子二: // 聲明三個對象,每個對象都有屬性id和date<br />var a = new Object();<br />var b = new Object();<br />var c = new Object();<br />a.id = 1;<br />b.id = 2;<br />c.id = 3;<br />a.date = new Date(2006,3,12);<br />b.date = new Date(2006,1,15);<br />c.date = new Date(2006,2,10);<br />// 存放在arr數組中<br />var arr = [a, b, c];<br />debugger; // 開始調試,留意id的排列是1、2、3按順序的<br />arr.sort(<br /> function (x,y) {<br /> return x.date-y.date;<br /> }<br />);<br />debugger;// 已經對arr排序了,我們發現元素順序發生變化,id也發生變化。排序的依據是按照日期的“從早到晚”。

數組排序的時候就會執行function (x,y) {return x.date-y.date; }這個傳入的函數。按照例子一沒有傳入任何排序參數,那樣預設就是,當x大於y的時候返回1,當x等於y的時候返回0,當x小於y的時候返回-1。如果按照例子二的情形,就是對x.date和y.date操作而已。日期的“從早到晚”或者數字型的“從小到大”(例子一),無論哪一個,對於sort()而言結果都是相同的。另外補充一點,比較日期同樣可以使用“加法+/減法-”的比較早晚,如果字元的話,則可使用<、>比較。

函數作為參數的用法瞭解過之後,我們來看看作為傳回值時候的函數,如例子三為一段內容加上HTML tag,請看例子三。

例子三: // 定義一個wrap函數,該函數的主要用途是產生一個包裹函數。<br />function wrap(tag) {<br /> var stag = '<' + tag + '>';<br /> var etag = '</' + tag.replace(/s.*/,'') + '>';<br /> return function(x) {<br /> return stag + x + etag;<br /> }<br />} </p><p>// 示範<br />var B = wrap('B');<br />document.write(B('粗粗體字'));<br />// 完全等價於<br />document.write('<br>');<br />document.write(wrap('B')('粗體字'));

var B = wrap('B');這一語句已經決定了這是一個“加粗體”的特別函數,執行該B()函數就會發生 <b>……內容……</b>的效果。若wrap('div')便是產生 <div>……內容……</div>,wrap('li')便是產生 <li>……內容……</li>……如此類推。 wrap('B')返回到變數B的即是一個函數。若不使用變數,也可以直接如等價的例子那樣wrap('B')亦是合法的JavaScript語句,之前最後一個括弧()前面的是函數類型的值即可。為什麼stag + x + etag中stag/etag沒有輸入也會在wrap()內部定義?因為warp範圍中就有stag、etag兩個變數。如果從理論上描述這一特性,應該屬於閉包(closure)方面的內容了。

 

譯寫自《Higher Order Programming In Javascript》。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.