国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript函數式編程(1):基本思想

y1chuan / 2646人閱讀

摘要:中的函數式編程思想匿名函數在函數式編程語言中,函數是可以沒有名字的,匿名函數通常表示可以完成某件事的一塊代碼。匿名函數中包含對的局部變量的引用,因此當返回時,的值被保留不會被垃圾回收機制回收,持續調用,將會改變的值。

1 函數式編程簡介

函數式編程是和傳統命令式編程區分的一種編程思想,“在函數式編程語言中,函數是第一類的對象,也就是說,函數 不依賴于任何其他的對象而可以獨立存在,而在面向對象的語言中,函數 ( 方法 ) 是依附于對象的,屬于對象的一部分。這一點決定了函數在函數式語言中的一些特別的性質,比如作為傳出 / 傳入參數,作為一個普通的變量等。[1]”

函數式編程思想的源頭可以追溯到 20 世紀 30 年代,數學家阿隆左 . 丘奇在進行一項關于問題的可計算性的研究,也就是后來的 lambda 演算。lambda 演算的本質為 一切皆函數,函數可以作為另外一個函數的輸出或者 / 和輸入,一系列的函數使用最終會形成一個表達式鏈,這個表達式鏈可以最終求得一個值,而這個過程,即為計算的本質。

然而,這種思想在當時的硬件基礎上很難實現,歷史最終選擇了同丘奇的 lambda 理論平行的另一種數學理論:圖靈機作為計算理論,而采取另一位科學家馮 . 諾依曼的計算機結構,并最終被實現為硬件。由于第一臺計算機即為馮 . 諾依曼的程序存儲結構,因此運行在此平臺的程序也繼承了這種基因,程序設計語言如 C/Pascal 等都在一定程度上依賴于此體系。

到了 20 世紀 50 年代,一位 MIT 的教授 John McCarthy 在馮 . 諾依曼體系的機器上成功的實現了 lambda 理論,取名為 LISP(LISt Processor), 至此函數式編程語言便開始活躍于計算機科學領域。

2 JavaScript中的函數式編程思想 2.1)匿名函數

在函數式編程語言中,函數是可以沒有名字的,匿名函數通常表示:“可以完成某件事的一塊代碼”。這種表達在很多場合是有用的,因為我們有時需要用函數完成某件事,但是這個函數可能只是臨時性的,那就沒有理由專門為其生成一個頂層的函數對象。

    //自定義map()
    function map(array, func){ 
        var res = []; 
        for ( var i = 0, len = array.length; i < len; i++){ 
                res.push(func(array[i])); 
            } 
        return res; 
    } 
    //匿名函數
    var mapped = map([1, 3, 5, 7, 8],  function (n){ 
        return n = n + 1; 
    }); 
    alert(mapped); //2,4,6,8,9// 對數組 [1,3,5,7,8] 中每一個元素加 1
2.2)柯里化

是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,或者說創建一個已經預先包含一個參數的函數,這其中會使用到閉包。
先來一個不是類似克里化的例子:

function add(num1, num2){
        return num1 + num2;
    }
    function curriedAdd(num2){
        return add(5, num2);
    }
    alert(add(2, 3)); //5
    alert(curriedAdd(3)); //8

這里的curriedAdd函數類似克里化,因為它固定了函數的一個參數。
下面看一個真正的函數克里化:

  //傳入的參數不止fn一個,但是只有fn顯式用到,所以明確給出

    function curry(fn){
            var args = Array.prototype.slice.call(arguments, 1);//得到外部函數參數
            return function(){
            var innerArgs = Array.prototype.slice.call(arguments);//得到內部函數參數
            var finalArgs = args.concat(innerArgs);//參數合并得到整體參數數組
            return fn.apply(null, finalArgs);//對整體參數數組運用函數fn
        };
    }
    function add(num1, num2){
        return num1 + num2;
    }
    var curriedAdd = curry(add, 5);
    alert(curriedAdd(3)); //8

根據上述實例,克里化一般通過curry()函數動態實現,curry()函數的主要工作就是將被返回函數的參數進行排序。 curry()的第一個參數是要進行柯里化的函數,其他參數是要傳入的值。為了獲取第一個參數之后的所有參數,在 arguments 對象上調用了 slice()方法,并傳入參數 1 表示被返回的數組包含從第二個參數開始的所有參數。然后 args 數組包含了來自外部函數的參數。在內部函數中,創建了 innerArgs 數組用來存放所有傳入的參數(又一次用到了 slice())。有了存放來自外部函數和內部函數的參數數組后,就可以使用 concat()方法將它們組合為 finalArgs,然后使用 apply()將結果傳遞給該函數。注意這個函數并沒有考慮到執行環境,所以調用 apply()時第一個參數是 null。

2.3)高階函數

即為對函數的進一步抽象,map(array, func) 的表達式已經表明,將 func 函數作用于 array 中的每一個元素,最終返回一個新的 array,應該注意的是,map 對 array 和 func 的實現是沒有任何預先的假設的(抽象),因此稱之為“高階”函數。

    function map(array, func){ 
      var res = []; 
      for ( var i = 0, len = array.length; i < len; i++){ 
             res.push(func(array[i])); 
         } 
          return res; 
     } 
     var mapped = map([1, 3, 5, 7, 8],  function (n){ 
          return n = n + 1; 
     }); 
    alert(mapped); 
    
    var mapped2 = map(["one", "two" , "three", "four"], 
      function (item){ 
          return "("+item+")"; 
     }); 
    alert(mapped2);

mapped 和 mapped2 均調用了 map,但是得到了截然不同的結果,因為 map 的參數本身已經進行了一次抽象,map 函數做的是第二次抽象,高階的“階”可以理解為抽象的層次。

2.4)閉包

閉包已經在另一篇文章《閉包:私有化變量》中介紹過,與閉包有關的垃圾回收機制在《垃圾回收機制——總結自《JavaScript高級程序設計》也有詳細介紹,因此這里僅僅簡要說明閉包。
當在一個函數 outter 內部定義另一個函數 inner,而 inner 又引用了 outter 作用域內的變量,在 outter 之外使用 inner 函數,則形成了閉包。

   

匿名函數 function(){return n++;} 中包含對 outter 的局部變量 n 的引用,因此當 outter 返回時,n 的值被保留 ( 不會被垃圾回收機制回收 ),持續調用 o1(),將會改變 n 的值。而 o2 的值并不會隨著 o1() 被調用而改變,第一次調用 o2 會得到 n==0 的結果,用面向對象的術語來說,就是 o1 和 o2 為不同的 實例,互不干涉。
閉包實例2:

//創建一個對象并壓入數組
var outter = [];
function clouseTest () {
var array = ["one", "two", "three", "four"];
for ( var i = 0; i < array.length;i++){

var x = {}; 
x.no = i; 
x.text = array[i]; 
 x.invoke =  function (){ 
     alert(i); 
    } 
outter.push(x); 
} 

}
//執行函數并調用每個數組元素對應的對象的方法
clouseTest();// 調用這個函數,向 outter 數組中添加對象
for ( var i = 0, len = outter.length; i < len; i++){

outter[i].invoke(); //4,4,4,4

}

由于 i 是閉包中的局部變量,for 循環最后退出時的值為 4,因此調用 outter 中的每個元素都會得到 4。
修正過后的閉包:

       

[1] http://www.ibm.com/developerw...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/50137.html

相關文章

  • JavaScript函數編程1):基本思想

    摘要:中的函數式編程思想匿名函數在函數式編程語言中,函數是可以沒有名字的,匿名函數通常表示可以完成某件事的一塊代碼。匿名函數中包含對的局部變量的引用,因此當返回時,的值被保留不會被垃圾回收機制回收,持續調用,將會改變的值。 1 函數式編程簡介 函數式編程是和傳統命令式編程區分的一種編程思想,在函數式編程語言中,函數是第一類的對象,也就是說,函數 不依賴于任何其他的對象而可以獨立存在,而在面向...

    時飛 評論0 收藏0
  • javascript 函數編程思想

    摘要:今天這篇文章主要介紹函數式編程的思想。函數式編程通過最小化變化使得代碼更易理解。在函數式編程里面,組合是一個非常非常非常重要的思想。可以看到函數式編程在開發中具有聲明模式。而函數式編程旨在盡可能的提高代碼的無狀態性和不變性。 最開始接觸函數式編程的時候是在小米工作的時候,那個時候看老大以前寫的代碼各種 compose,然后一些 ramda 的一些工具函數,看著很吃力,然后極力吐槽函數式...

    YPHP 評論0 收藏0
  • 編程模型(范)小結

    摘要:參考鏈接面向對象編程模型現在的很多編程語言基本都具有面向對象的思想,比如等等,而面向對象的主要思想對象,類,繼承,封裝,多態比較容易理解,這里就不多多描述了。 前言 在我們的日常日發和學習生活中會常常遇到一些名詞,比如 命令式編程模型,聲明式編程模型,xxx語言是面向對象的等等,這個編程模型到處可見,但是始終搞不清是什么?什么語言又是什么編程模型,當你新接觸一門語言的時候,有些問題是需...

    miya 評論0 收藏0
  • SegmentFault 技術周刊 Vol.16 - 淺入淺出 JavaScript 函數編程

    摘要:函數式編程,一看這個詞,簡直就是學院派的典范。所以這期周刊,我們就重點引入的函數式編程,淺入淺出,一窺函數式編程的思想,可能讓你對編程語言的理解更加融會貫通一些。但從根本上來說,函數式編程就是關于如使用通用的可復用函數進行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數式編程(Functional Programming),一...

    csRyan 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<