久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

用函數(shù)式編程技術(shù)編寫優(yōu)美的 JavaScript

 xnet 2006-07-27

2006 年 7 月 20 日

函數(shù)式或聲明性編程是非常強(qiáng)大的編程方法,,正逐漸在軟件行業(yè)流行起來。這篇文章將介紹一些相關(guān)的函數(shù)式編程概念,,并提供有效使用這些概念的示例,。作者將解釋如何使用 JavaScript(TM)?(JavaScript 能導(dǎo)入函數(shù)式編程的構(gòu)造和特性)編寫優(yōu)美的代碼。

簡介

函數(shù)式編程語言在學(xué)術(shù)領(lǐng)域已經(jīng)存在相當(dāng)長一段時(shí)間了,,但是從歷史上看,,它們沒有豐富的工具和庫可供使用。隨著 .NET 平臺上的 Haskell 的出現(xiàn),,函數(shù)式編程變得更加流行,。一些傳統(tǒng)的編程語言,例如 C++ 和 JavaScript,引入了由函數(shù)式編程提供的一些構(gòu)造和特性,。在許多情況下,,JavaScript 的重復(fù)代碼導(dǎo)致了一些拙劣的編碼。如果使用函數(shù)式編程,,就可以避免這些問題,。此外,可以利用函數(shù)式編程風(fēng)格編寫更加優(yōu)美的回調(diào),。

函數(shù)式編程

函數(shù)式編程只描述在程序輸入上執(zhí)行的操作,,不必使用臨時(shí)變量保存中間結(jié)果。重點(diǎn)是捕捉 “是什么以及為什么”,,而不是 “如何做”。與將重點(diǎn)放在執(zhí)行連續(xù)命令上的過程性編程相比,,函數(shù)式編程的重點(diǎn)是函數(shù)的定義而不是狀態(tài)機(jī)(state machine)的實(shí)現(xiàn),。

大型知識管理系統(tǒng)應(yīng)用程序從使用函數(shù)式編程風(fēng)格上受益頗多,因?yàn)楹瘮?shù)式編程簡化了開發(fā),。

因?yàn)楹瘮?shù)式編程采用了完全不同的組織程序的方式,,所以那些習(xí)慣于采用命令式范例的程序員可能會發(fā)現(xiàn)函數(shù)式編程有點(diǎn)難學(xué)。在這篇文章中,,您將了解一些關(guān)于如何采用函數(shù)式風(fēng)格,,用 JavaScript 編寫良好的、優(yōu)美的代碼的示例,。我將討論:

  • 函數(shù)式編程概念,,包括匿名函數(shù)、調(diào)用函數(shù)的不同方法,,以及將函數(shù)作為參數(shù)傳遞給其他函數(shù)的方式,。

     

  • 函數(shù)式概念的運(yùn)用,采用的示例包括:擴(kuò)展數(shù)組排序,;動態(tài) HTML 生成的優(yōu)美代碼,;系列函數(shù)的應(yīng)用。

 


函數(shù)式編程概念

請告訴每個(gè)人,。請把這個(gè)提交給:

digg Digg
slashdot Slashdot

在那些通過描述 “如何做” 指定解決問題的方法的語言中,,許多開發(fā)人員都知道如何進(jìn)行編碼。例如,,要編寫一個(gè)計(jì)算階乘的函數(shù),,我可以編寫一個(gè)循環(huán)來描述程序,或者使用遞歸來查找所有數(shù)字的乘積,。在這兩種情況下,,計(jì)算的過程都在程序中進(jìn)行了詳細(xì)說明。清單 1 顯示了一個(gè)計(jì)算階乘的可能使用的 C 代碼。


清單 1. 過程風(fēng)格的階乘
                        int factorial (int n)
                        {
                        if (n <= 0)
                        return 1;
                        else
                        return n * factorial (n-1);
                        }
                        

這類語言也叫做過程性 編程語言,,因?yàn)樗鼈兌x了解決問題的過程,。函數(shù)式編程與這個(gè)原理有顯著不同。在函數(shù)式編程中,,需要描述問題 “是什么”,。 函數(shù)式編程語言又叫做聲明性 語言。同樣的計(jì)算階乘的程序可以寫成所有到 n 的數(shù)字的乘積,。計(jì)算階乘的典型函數(shù)式程序看起來如 清單 2 中的示例所示,。


清單 2. 函數(shù)式風(fēng)格的階乘
                        factorial n, where n <= 0 	:= 1
                        factorial n    := foldr * 1 take n [1..]
                        

第二個(gè)語句指明要得到從 1 開始的前 n 個(gè)數(shù)字的列表(take n [1..]),然后找出它們的乘積,,1 為基元,。這個(gè)定義與前面的示例不同,沒有循環(huán)或遞歸,。它就像階乘函數(shù)的算術(shù)定義,。一旦了解了庫函數(shù)(takefoldr)和標(biāo)記(list notation [ ])的意義,編寫代碼就很容易,,而且可讀性也很好,。

只用三行 Miranda 代碼就可以編寫例程,根據(jù)參數(shù),,使用廣度優(yōu)先或深度優(yōu)先遍歷處理 n 叉樹的每個(gè)節(jié)點(diǎn),,而且元素可以是任何通用類型。

從歷史上看,,函數(shù)式編程語言不太流行有各種原因,。但是最近,有些函數(shù)式編程語言正在進(jìn)入計(jì)算機(jī)行業(yè),。其中一個(gè)例子就是 .NET 平臺上的 Haskell,。其他情況下,現(xiàn)有的一些語言借用了函數(shù)式編程語言中的一些概念,。一些 C++ 實(shí)現(xiàn)中的迭代器和 continuation,,以及 JavaScript 中提供的一些函數(shù)式構(gòu)造(functional construct),就是這種借用的示例,。但是,,通過借用函數(shù)式構(gòu)造,總的語言編程范例并沒有發(fā)生變化,。JavaScript 并沒因?yàn)楹瘮?shù)式構(gòu)造的添加就變成了函數(shù)式編程語言,。

我現(xiàn)在要討論 JavaScript 中的函數(shù)式構(gòu)造的各種美妙之處,以及在日常編碼和工作中使用它們的方式,。我們將從一些基本功能開始,,然后用它們查看一些更有趣的應(yīng)用,。

匿名函數(shù)

在 JavaScript 中,可以編寫匿名函數(shù)或沒有名稱的函數(shù),。為什么需要這樣的函數(shù),?請繼續(xù)往下讀,但首先我們將學(xué)習(xí)如何編寫這樣一個(gè)函數(shù),。如果擁有以下 JavaScript 函數(shù):
清單 3. 典型的函數(shù)

                        function sum(x,y,z) {
                        return (x+y+z);
                        }
                        

然后對應(yīng)的匿名函數(shù)看起來應(yīng)當(dāng)如下所示:
清單 4. 匿名函數(shù)

                        function(x,y,z) {
                        return (x+y+z);
                        }
                        

要使用它,,則需要編寫以下代碼:


清單 5. 應(yīng)用匿名函數(shù)
                        var sum = function(x,y,z) {
                        return (x+y+z);
                        }(1,2,3);
                        alert(sum);
                        

使用函數(shù)作為值

也可以將函數(shù)作為值使用。還可以擁有一些所賦值是函數(shù)的變量,。在最后一個(gè)示例中,,還可以執(zhí)行以下操作:
清單 6. 使用函數(shù)賦值

                        var sum = function(x,y,z) {
                        return (x+y+z);
                        }
                        alert(sum(1,2,3));
                        

在上面 清單 6 的示例中,為變量 sum 賦的值是函數(shù)定義本身,。這樣,,sum 就成了一個(gè)函數(shù),可以在任何地方調(diào)用,。

調(diào)用函數(shù)的不同方法

JavaScript 允許用兩種方式調(diào)用函數(shù),,如清單 78 所示。


清單 7. 典型的函數(shù)應(yīng)用
                        alert (“Hello, World!");
                        


清單 8. 用函數(shù)作為表達(dá)式
                        (alert) (“Hello, World!");
                        

所以也可以編寫以下代碼:


清單 9. 定義函數(shù)之后就可以立即使用它
( function(x,y,z) { return (x+y+z) } ) (1, 2, 3);
                        

可以在括號中編寫函數(shù)表達(dá)式,,然后傳遞給參數(shù),對參數(shù)進(jìn)行運(yùn)算,。雖然在 清單 8 的示例中,,有直接包含在括號中的函數(shù)名稱,但是按 清單 9 中所示方式使用它時(shí),,就不是這樣了,。

將函數(shù)作為參數(shù)傳遞給其他函數(shù)

也可以將函數(shù)作為參數(shù)傳遞給其他函數(shù)。雖然這不是什么新概念,,但是在后續(xù)的示例中大量的使用了這個(gè)概念,。可以傳遞函數(shù)參數(shù),,如 清單 10 所示,。


清單 10. 將函數(shù)作為參數(shù)傳遞,并應(yīng)用該函數(shù)
                        var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };
                        var sum = function(x,y,z) {
                        return x+y+z;
                        };
                        alert( passFunAndApply(sum,3,4,5) ); // 12
                        

執(zhí)行最后一個(gè) alert 語句輸出了一個(gè)大小為 12 的值,。

使用函數(shù)式概念

前一節(jié)介紹了一些使用函數(shù)式風(fēng)格的編程概念,。所給的示例并沒有包含所有的概念,它們在重要性方面也沒有先后順序,,只是一些與這個(gè)討論有關(guān)的概念而已,。下面對 JavaScript 中的函數(shù)式風(fēng)格作一快速總結(jié):

  • 函數(shù)并不總是需要名稱。
  • 函數(shù)可以像其他值一樣分配給變量,。
  • 函數(shù)表達(dá)式可以編寫并放在括號中,,留待以后應(yīng)用。
  • 函數(shù)可以作為參數(shù)傳遞給其他函數(shù)。

 

這一節(jié)將介紹一些有效使用這些概念編寫優(yōu)美的 JavaScript 代碼的示例,。(使用 JavaScript 函數(shù)式風(fēng)格,,可以做許多超出這個(gè)討論范圍的事。)

擴(kuò)展數(shù)組排序
先來編寫一個(gè)排序方法,,可以根據(jù)數(shù)組元素的日期對數(shù)據(jù)進(jìn)行排序,。用 JavaScript 編寫這個(gè)方法非常簡單。數(shù)據(jù)對象的排序方法接受一個(gè)可選參數(shù),,這個(gè)可選參數(shù)就是比較函數(shù),。在這里,需要使用 清單 11 中的比較函數(shù),。


清單 11. 比較函數(shù)

function (x,y) {
                        return x.date – y.date;
                        }
                        

要得到需要的函數(shù),,請使用 清單 12 的示例。


清單 12. 排序函數(shù)的擴(kuò)展
arr.sort( function (x,y) {	return x.date – y.date; } );
                        

其中 arr 是類型數(shù)組對象,。排序函數(shù)會根據(jù) arr 數(shù)組中對象的日期對所有對象進(jìn)行排序,。比較函數(shù)和它的定義一起被傳遞給排序函數(shù),以完成排序操作,。使用這個(gè)函數(shù):

  • 每個(gè) JavaScript 對象都有一個(gè) date 屬性,。
  • JavaScript 的數(shù)組類型的排序函數(shù)接受可選參數(shù),可選參數(shù)是用來排序的比較函數(shù),。這與 C 庫中的 qsort 函數(shù)類似,。

 

動態(tài)生成 HTML 的優(yōu)美代碼
在這個(gè)示例中,將看到如何編寫優(yōu)美的代碼,,從數(shù)組動態(tài)地生成 HTML,。可以根據(jù)從數(shù)據(jù)中得到的值生成表格,?;蛘撸部梢杂脭?shù)組的內(nèi)容生成排序和未排序的列表,。也可以生成垂直或水平的菜單項(xiàng)目,。

清單 13 中的代碼風(fēng)格通常被用來從數(shù)組生成動態(tài) HTML。


清單 13. 生成動態(tài) HTML 的普通代碼
var str=‘ ‘;
                        for (var i=0;i<arr.length;i++) {
                        var element=arr[i];
                        str+=... HTML generation code...
                        }
                        document.write(str);
                        

可以用 清單 14 的代碼替換這個(gè)代碼,。


清單 14. 生成動態(tài) HTML 的通用方式
                        Array.prototype.fold=function(templateFn) {
                        var len=this.length;
                        var str=‘ ‘;
                        for (var i=0 ; i<len ; i++)
                        str+=templateFn(this[i]);
                        return str;
                        }
                        function templateInstance(element) {
                        return ... HTML generation code ...
                        }
                        document.write(arr.fold(templateInstance));
                        

我使用 Array 類型的 prototype 屬性定義新函數(shù) fold?,F(xiàn)在可以在后面定義的任何數(shù)組中使用該函數(shù)。

系列函數(shù)的應(yīng)用
考慮以下這種情況:想用一組函數(shù)作為回調(diào)函數(shù),。為實(shí)現(xiàn)這一目的,,將使用 window.setTimeout 函數(shù),該函數(shù)有兩個(gè)參數(shù),。第一個(gè)參數(shù)是在第二個(gè)參數(shù)表示的毫秒數(shù)之后被調(diào)用的函數(shù),。清單 15 顯示了完成此操作的一種方法,。
清單 15. 在回調(diào)中調(diào)用一組函數(shù)
window.setTimeout(function(){alert(‘First!’);alert(‘Second!’);}, 5000);
                        

清單 16 顯示了完成此操作的更好的方式。


清單 16. 調(diào)用系列函數(shù)的更好的方式
Function.prototype.sequence=function(g) {
                        var f=this;
                        return function() {
                        f();g();
                        }
                        };
                        function alertFrst() { alert(‘First!’); }
                        function alertSec() { alert(‘Second!’); }
                        setTimeout( alertFrst.sequence(alertSec), 5000);
                        

在處理事件時(shí),,如果想在調(diào)用完一個(gè)回調(diào)之后再調(diào)用一個(gè)回調(diào),,也可以使用 清單 16 中的代碼擴(kuò)展。這可能是一個(gè)需要您自行完成的一個(gè)練習(xí),,現(xiàn)在您的興趣被點(diǎn)燃了吧,。



在許多領(lǐng)域中都可以應(yīng)用 JavaScript 中的函數(shù)式編程,以優(yōu)美的方式完成日?;顒?。這篇文章中的示例只介紹了幾種情況。如果您找到了函數(shù)式編程的合適場景,,并應(yīng)用這些概念,,那么您就會有更多的理解,并且可以增加您的優(yōu)美程度,。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多