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

資訊專欄INFORMATION COLUMN

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

時(shí)飛 / 2269人閱讀

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

1 函數(shù)式編程簡介

函數(shù)式編程是和傳統(tǒng)命令式編程區(qū)分的一種編程思想,“在函數(shù)式編程語言中,函數(shù)是第一類的對(duì)象,也就是說,函數(shù) 不依賴于任何其他的對(duì)象而可以獨(dú)立存在,而在面向?qū)ο蟮恼Z言中,函數(shù) ( 方法 ) 是依附于對(duì)象的,屬于對(duì)象的一部分。這一點(diǎn)決定了函數(shù)在函數(shù)式語言中的一些特別的性質(zhì),比如作為傳出 / 傳入?yún)?shù),作為一個(gè)普通的變量等。[1]”

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

然而,這種思想在當(dāng)時(shí)的硬件基礎(chǔ)上很難實(shí)現(xiàn),歷史最終選擇了同丘奇的 lambda 理論平行的另一種數(shù)學(xué)理論:圖靈機(jī)作為計(jì)算理論,而采取另一位科學(xué)家馮 . 諾依曼的計(jì)算機(jī)結(jié)構(gòu),并最終被實(shí)現(xiàn)為硬件。由于第一臺(tái)計(jì)算機(jī)即為馮 . 諾依曼的程序存儲(chǔ)結(jié)構(gòu),因此運(yùn)行在此平臺(tái)的程序也繼承了這種基因,程序設(shè)計(jì)語言如 C/Pascal 等都在一定程度上依賴于此體系。

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

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

在函數(shù)式編程語言中,函數(shù)是可以沒有名字的,匿名函數(shù)通常表示:“可以完成某件事的一塊代碼”。這種表達(dá)在很多場合是有用的,因?yàn)槲覀冇袝r(shí)需要用函數(shù)完成某件事,但是這個(gè)函數(shù)可能只是臨時(shí)性的,那就沒有理由專門為其生成一個(gè)頂層的函數(shù)對(duì)象。

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

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

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

這里的curriedAdd函數(shù)類似克里化,因?yàn)樗潭撕瘮?shù)的一個(gè)參數(shù)。
下面看一個(gè)真正的函數(shù)克里化:

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

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

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

2.3)高階函數(shù)

即為對(duì)函數(shù)的進(jìn)一步抽象,map(array, func) 的表達(dá)式已經(jīng)表明,將 func 函數(shù)作用于 array 中的每一個(gè)元素,最終返回一個(gè)新的 array,應(yīng)該注意的是,map 對(duì) array 和 func 的實(shí)現(xiàn)是沒有任何預(yù)先的假設(shè)的(抽象),因此稱之為“高階”函數(shù)。

    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 均調(diào)用了 map,但是得到了截然不同的結(jié)果,因?yàn)?map 的參數(shù)本身已經(jīng)進(jìn)行了一次抽象,map 函數(shù)做的是第二次抽象,高階的“階”可以理解為抽象的層次。

2.4)閉包

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

   

匿名函數(shù) function(){return n++;} 中包含對(duì) outter 的局部變量 n 的引用,因此當(dāng) outter 返回時(shí),n 的值被保留 ( 不會(huì)被垃圾回收機(jī)制回收 ),持續(xù)調(diào)用 o1(),將會(huì)改變 n 的值。而 o2 的值并不會(huì)隨著 o1() 被調(diào)用而改變,第一次調(diào)用 o2 會(huì)得到 n==0 的結(jié)果,用面向?qū)ο蟮男g(shù)語來說,就是 o1 和 o2 為不同的 實(shí)例,互不干涉。
閉包實(shí)例2:

//創(chuàng)建一個(gè)對(duì)象并壓入數(shù)組
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); 
} 

}
//執(zhí)行函數(shù)并調(diào)用每個(gè)數(shù)組元素對(duì)應(yīng)的對(duì)象的方法
clouseTest();// 調(diào)用這個(gè)函數(shù),向 outter 數(shù)組中添加對(duì)象
for ( var i = 0, len = outter.length; i < len; i++){

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

}

由于 i 是閉包中的局部變量,for 循環(huán)最后退出時(shí)的值為 4,因此調(diào)用 outter 中的每個(gè)元素都會(huì)得到 4。
修正過后的閉包:

       

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

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/80648.html

相關(guān)文章

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

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

    y1chuan 評(píng)論0 收藏0
  • javascript 函數(shù)編程思想

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

    YPHP 評(píng)論0 收藏0
  • 編程模型(范)小結(jié)

    摘要:參考鏈接面向?qū)ο缶幊棠P同F(xiàn)在的很多編程語言基本都具有面向?qū)ο蟮乃枷耄热绲鹊龋嫦驅(qū)ο蟮闹饕枷雽?duì)象,類,繼承,封裝,多態(tài)比較容易理解,這里就不多多描述了。 前言 在我們的日常日發(fā)和學(xué)習(xí)生活中會(huì)常常遇到一些名詞,比如 命令式編程模型,聲明式編程模型,xxx語言是面向?qū)ο蟮牡鹊龋@個(gè)編程模型到處可見,但是始終搞不清是什么?什么語言又是什么編程模型,當(dāng)你新接觸一門語言的時(shí)候,有些問題是需...

    miya 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.16 - 淺入淺出 JavaScript 函數(shù)編程

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

    csRyan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<