《JavaScript編程精解》讀書筆記-第五章:函數式編程

來源:互聯網
上載者:User

5.1抽象:歸根結底程式是要解決生活中的問題,但多數時候現實中的問題總是很複雜,而盡量降低程式複雜程度的辦法就是進行抽象化處理。把許多實際的複雜關係抽象成更簡單的邏輯運用到程式當中。這是我對編程中抽象的理解。函數式編程就是通過巧妙的函數組合來建立抽象。

5.2高階函數:簡單點說高階函數就是處理其他函數的函數,也就是函數的嵌套。js是面向函數的一門語言,在js的世界裡任何東西都是實值型別的,當然函數也不例外。它與其他語言(比如說C#)最明顯的差異就是函數能夠完全像值一樣去產生,去傳遞。你可以把函數作為另一個函數的參數來使用,也可以在一個函數的內部再定義一個新的函數。當然你也許會想到C#中的lambda運算式,確實也能完成一些類似的功能,但js是純動態語言,處理函數是它的看家本領,C#中lambda,var的運用只是在一定程度上增加了動態性,靈活性上還是遠不如js的。前面說的這些是我個人的一些理解,書中並沒講這些,書裡面多是以執行個體的形式來展現函數編程的,下面我們用代碼試試看(當然,代碼也一定跟書上一樣,有些是高仿的)。

一個最簡單的函數式編程的例子

View Code

function calculate(calMethod,numA,numB){    return calMethod(numA,numB);}function add(num1,num2){    return num1+num2;}function multiply(num1,num2){    return num1*num2;}var result1 = calculate(add,1,2);var result2 = calculate(multiply,1,2);alert("result1:"+result1+",result2:"+result2);

 在上面的例子中,函數就是值的特性一目瞭然。還有一個常用的高階函數的類型就是修改函數,作用是修改了傳入的函數的值,如下: 

View Code

function initMethod(method1){    return function(num1)    {        return method1(num1);    }}function changedMethod(num1){    return num1*num1;}var testMethod = initMethod(changedMethod);var result = testMethod(2);alert(result);

上面這個例子讓我想起最近asp.net的mvc中的依賴注入,把帶有具體功能的一個對象通過C#中建構函式傳到當前類中,當前類中的功能其實是靠傳過來的對象實現的。代理模式應該也是這樣的。

我們常見的sum()函數,其實是一個演算法的變體,而這個函數就是規約函數,下面是規約函數的一個例子:

View Code

//規約函數function reduce(combine,base,array){    forEach(array,function(element){        base = combine(base,element);    });    return base;}function add(a,b){    return a+b;}function forEach(array,action){    for(var i = 0; i< array.length; i++){        action(array[i]);    }}function sum(numbers){    return reduce(add,0,numbers);}alert(sum([1,2,3]));

 reduce函數通過重複的調用一個函數,將一個數組裡面的所有的值都加到一個基礎資料base上。這樣就能對數組裡的所有值按照一定規則計算,這裡是相加,改變combine參數來具體實現你自己想要的運算。另外注意的是函數作為參數傳遞時放在第一位置,這是慣例,至於具體原因,書中聲明後面會講到。

到此為止我稍微總結了一下函數內部讀取函數的情況:

1.條用外部的函數(最起碼的)。

2.能夠讀取作為參數傳進來的函數。

3.能夠在當前函數內部定義函數,並調用該函數。

4.能夠讀取該函數自身(遞迴)。

再看一個函數,目的是接受一個數組,返回數組裡面值為0的個數。

View Code

function reduce(combine,base,array){    forEach(array,function(element){        base = combine(base,element);    });    return base;}function forEach(array,action){    for(var i = 0; i< array.length; i++){        action(array[i]);    }}function countZeros(array){    function counter(total,element){        return total + (0 === element ? 1 : 0);        //下面注釋掉的這一行是一個替代方案        //return total + (0 === element);    }    return reduce(counter,0,array);}alert(countZeros([0,1,0,0,0,0,1,1,1,1]));/*帥!,能把true轉成整型啊,true就是1,false就是0.var a = 1 + true;alert(a);*//*var a = 1+ false;alert(a);*/

   上面這個例子中return total + (0 === element ? 1 : 0)用的十分巧妙,但我嘗試了一種新的實現方法return total + (0===element),經過實驗我發現其實bool與number相加的時候true會變成1,false會變成0,這樣在很多情況下都可以判斷跟加減運算一氣呵成了,挺好。

接下來是一個映射數組,這是一個與數組相關的基本演算法。跟前面的規約函數一樣可以處理數組中的每個數值,但是函數的傳回值並不會被丟棄,而是重新構建一個函數。

View Code

function forEach(array,action){    for(var i = 0; i< array.length; i++){        action(array[i]);    }}//映射數組function map(func,array){    var result = [];    forEach(array,function(element){        result.push(func(element));    });    return result;}alert(map(Math.round,[1.1,3.3,2.2]));

 5.4其他函數技巧:在用高階函數的時候,js操作符都不是函數,就像前面的例子,我們需要定義一個add函數,但每次這樣編寫並調用顯然很煩躁,我們可以這樣幹:

View Code

var op = {    "+":function(a,b){return a+b;},    "==":function(a,b){return a==b;},    "===":function(a,b){return a===b;},    "!":function(a){return !a;}           /*等等,可以任意添加自己常用的操作*/}//下面的方式來完成求和reduce(op["+"],0,[1,2,3,4,5,6]);

 備忘:javascript常用函數

1.call()  via

View Code

//call()函數的用法一function Class1() {     this.name = "class1";     this.showNam = function()     {         alert(this.name);     } } function Class2() {     this.name = "class2"; } var c1 = new Class1(); var c2 = new Class2(); //call函數使得c1中的方法能夠在c2這個對象上執行c1.showNam.call(c2); //result:class2//call()函數的用法二function Class1() {     this.showTxt = function(txt)     {         alert(txt);     } } function Class2() {     //在Class2中調用Class1.call,就是把Class1中的對象覆蓋當前對象,以此來完成繼承。    Class1.call(this); } var c2 = new Class2(); c2.showTxt("cc"); 

 2.與call()相對應的還有一個apply()方法。關於兩者的差異請看:http://www.cnblogs.com/fighting_cp/archive/2010/09/20/1831844.html

後記:這一章的內容雖然總量不大,但牽扯到演算法的比較多,還有一部分自己沒理解好的就沒寫。自己不理解的,真是寫不出來,以後開始每天看點,慢慢的補充上。 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.