<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        JavaScript中有趣的反柯里化

        來源:懂視網 責編:小采 時間:2020-11-27 20:30:41
        文檔

        JavaScript中有趣的反柯里化

        JavaScript中有趣的反柯里化:反科里化的話題來自javascript之父Brendan Eich去年的一段twitter. 近幾天研究了一下,覺得這個東東非常有意思,分享一下。先忘記它的名字,看下它能做什么.不要小看這個功能,試想下,我們在寫一個庫的時候,時常會寫這樣的代碼,拿webQQ的Jx庫舉例。
        推薦度:
        導讀JavaScript中有趣的反柯里化:反科里化的話題來自javascript之父Brendan Eich去年的一段twitter. 近幾天研究了一下,覺得這個東東非常有意思,分享一下。先忘記它的名字,看下它能做什么.不要小看這個功能,試想下,我們在寫一個庫的時候,時常會寫這樣的代碼,拿webQQ的Jx庫舉例。
        反科里化的話題來自javascript之父Brendan Eich去年的一段twitter. 近幾天研究了一下,覺得這個東東非常有意思,分享一下。先忘記它的名字,看下它能做什么.

        20120301085946697.png

        不要小看這個功能,試想下,我們在寫一個庫的時候,時常會寫這樣的代碼,拿webQQ的Jx庫舉例。

        20120301085946697.png

        我們想要的,其實只是借用Array原型鏈上的一些函數。并沒有必要去顯式的構造一個新的函數來改變它們的參數并且重新運算。

        如果用uncurrying的方式顯然更加優雅和美妙,就像這樣:

        20120301085946697.png

        還能做很多有趣和方便的事情.

        甚至還能把call和apply方法都uncurrying,把函數也當作普通數據來使用. 使得javascript中的函數調用方式更像它的前生scheme, 當函數名本身是個變量的時候, 這種調用方法特別方便.

        scheme里面調用函數是這樣:

        20120301085946697.png

        javascript里可以寫的很接近.

        20120301085946697.png

        再看看jquery庫,由于jquery對象( 即通過$()創建的對象 )是一個對象冒充的偽數組,它有length屬性,并且能夠通過下標查找對應的元素,當需要給jquery對象添加一個成員時, 偽代碼大概是:

        20120301085946697.png

        如果用uncurrying的話, 就可以

        20120301085946697.png

        借用了array對象的push函數, 讓引擎去自動管理數組成員和length屬性.

        而且可以一次把需要的函數全部借過來, 一勞永逸. 一段測試代碼:

        20120301085946697.png

        總的來說, 使用uncurrying技術, 可以讓任何對象擁有原生對象的方法. 好了,如果到這里依然沒有引起你的興趣,那么你可以去干點別的了。

        接下來一步一步來看看原理以及實現。

        在了解反currying化這個奇怪的名字之前,我們得先搞清楚currying。

        維基百科上的定義:科里化( currying ); 又稱部分求值,是把接受多個參數的函數變換成接受一個單一參數的函數,并且返回接受余下的參數并且返回結果的新函數的技術。

        通俗點講,currying有點類似買房子時分期付款的方式,先給一部分首付( 一部分參數 ), 返回一個存折( 返回一個函數 ),合適的時候再給余下的參數并且求值計算。

        來看看我們都用過的currying, 我們經常在綁定context 的時候實現一個Function.prototype.bind函數.

        20120301085946697.png

        高階函數是實現currying的基礎, 所謂高階函數至少滿足這2個特性:

        1, 函數可以當作參數傳遞,

        2, 函數可以作為返回值。

        Javascript在設計之初,參考了很多scheme語言的特性。而scheme是函數式語言鼻祖lisp的2大方言之一,所以javascript也擁有一些函數式語言的特性,包括高階函數,閉包,lambda表達式等。

        當javascript中的函數返回另一個函數,此時會形成一個閉包,而在閉包中就可以保存第一次運算的參數,我們用這個思想,來寫一個通用的currying函數。

        20120301085946697.png

        我們約定, 當傳入參數時候, 繼續currying化, 參數為空時才開始求值.

        假設在實現一個計算每月花費的函數, 每天結束前我們都要記錄今天花了多少錢, 但我們只關心月底的花費總值, 無需每天都計算一次.

        20120301085946697.png

        使用currying函數, 便可以延遲到最后一刻才一起計算, 好處不言而喻, 在很多場合可以避免無謂的計算, 節省性能, 也是實現惰性求值的一種方案.

        好了,現在才走進正題,

        curring是預先填入一些參數.

        反curring就是把原來已經固定的參數或者this上下文等當作參數延遲到未來傳遞.

        其實就是搞這樣一個事情,將:

        1

        obj.foo( arg1 ) //foo本來是只在obj上的函數. 就像push原本只在Array.prototype上

        轉化成這樣的形式

        1

        foo( obj, arg1 ) // 跟我們舉的第一個例子一樣.將[].push轉換成push( [] )

        就像原本是接在電視插頭上的插座,把它拆下來之后,其實也能用來接冰箱。

        Ecma上Array和String的每個原型方法后面都有這么一段話,比如push:

        NOTE The push function is intentionally generic; it does not require that its this value be an Array object.

        Therefore it can be transferred to other kinds of objects for use as a method. Whether the concat function can be applied.

        Javascript為什么要這樣設計, 我們先來復習下動態語言中重要的鴨子類型思想.

        說個故事:

        很久以前有個皇帝喜歡聽鴨子呱呱叫,于是他召集大臣組建一個一千只鴨子的合唱團。大臣把全國的鴨子都抓來了,最后始終還差一只。有天終于來了一只自告奮勇的雞,這只雞說它也會呱呱叫,好吧在這個故事的設定里,它確實會呱呱叫。 后來故事的發展很明顯,這只雞混到了鴨子的合唱團中。— 皇帝只是想聽呱呱叫,他才不在乎你是鴨子還是雞呢。

        這個就是鴨子類型的概念,在javascript里面,很多函數都不做對象的類型檢測,而是只關心這些對象能做什么。

        Array構造器和String構造器的prototype上的方法就被特意設計成了鴨子類型。這些方法不對this的數據類型做任何校驗。這也就是為什么arguments能冒充array調用push方法.

        看下v8引擎里面Array.prototype.push的代碼:

        function ArrayPush() {

        var n = TO_UINT32( this.length );

        var m = %_ArgumentsLength();

        for (var i = 0; i < m; i++) {

        this[i+n] = %_Arguments(i); //屬性拷貝

        this.length = n + m; //修正length

        return this.length;

        }

        }

        可以看到,ArrayPush方法沒有對this的類型做任何顯示的限制,所以理論上任何對象都可以被傳入ArrayPush這個訪問者。

        我們需要解決的只剩下一個問題, 如何通過一種通用的方式來使得一個對象可以冒充array對象。

        真正的實現代碼其實很簡單:

        20120301085946697.png

        這段代碼雖然很短, 初次理解的時候還是有點費力. 我們拿push的例子看看它發生了什么.

        var push = Array.prototype.push.uncurrying();

        push( obj, ‘first’ );

        20120301085946697.png

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        JavaScript中有趣的反柯里化

        JavaScript中有趣的反柯里化:反科里化的話題來自javascript之父Brendan Eich去年的一段twitter. 近幾天研究了一下,覺得這個東東非常有意思,分享一下。先忘記它的名字,看下它能做什么.不要小看這個功能,試想下,我們在寫一個庫的時候,時常會寫這樣的代碼,拿webQQ的Jx庫舉例。
        推薦度:
        標簽: js 有趣 有意思
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲人色婷婷成人网站在线观看| 在线视频免费观看高清| 亚洲日韩VA无码中文字幕| 精品成人一区二区三区免费视频 | 人妻巨大乳hd免费看| 又粗又大又长又爽免费视频| 美女露100%胸无遮挡免费观看| 国产在线观看免费完整版中文版| 亚洲av无码偷拍在线观看| 啊灬啊灬别停啊灬用力啊免费看| 免费无码国产在线观国内自拍中文字幕 | 亚洲人成人网毛片在线播放| 在线免费观看一级片| 老湿机一区午夜精品免费福利| 亚洲熟伦熟女新五十路熟妇 | 亚洲成av人片天堂网| 日本视频一区在线观看免费| 亚洲一区二区三区在线观看蜜桃 | 国产成人综合亚洲AV第一页| 国产成人一区二区三区视频免费| 亚洲精品国产成人中文| 免费观看的av毛片的网站| 曰批全过程免费视频观看免费软件| 精品国产香蕉伊思人在线在线亚洲一区二区 | 香港a毛片免费观看| 亚洲videos| 伊人久久亚洲综合影院| 插鸡网站在线播放免费观看| 亚洲特级aaaaaa毛片| 免费人成年激情视频在线观看| 免费无码av片在线观看 | 日本亚洲色大成网站www久久| 亚洲精品老司机在线观看| 一区二区三区四区免费视频| 亚洲欧洲AV无码专区| 亚洲色中文字幕无码AV| 操美女视频免费网站| 91视频免费观看| 亚洲另类自拍丝袜第五页| 久久99国产亚洲精品观看| 国产免费131美女视频|