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

資訊專欄INFORMATION COLUMN

邂逅函數(shù)柯里化

Kross / 3258人閱讀

摘要:柯里化函數(shù)的作用函數(shù)柯里化允許和鼓勵你分隔復(fù)雜功能變成更小更容易分析的部分。指向的是調(diào)用方法的一個函數(shù),綁定,延遲執(zhí)行可見,之后返回的是一個延遲執(zhí)行的新函數(shù)關(guān)于性能的備注通常,使用柯里化會有一些開銷。

引子

有這樣一道題目,實(shí)現(xiàn)一個函數(shù),實(shí)現(xiàn)如下功能:

</>復(fù)制代碼

  1. var result = sum(1)(2)(3);
  2. console.log(result);//6

這道題目,印象中是一道技術(shù)筆試題。結(jié)合查到的資料,在這里做一下簡單的分析和總結(jié)。

一個簡單的例子

題目給的還是比較寬的,沒多少限制,給了很多自由發(fā)揮的空間。

下面我們就一步一步的去實(shí)現(xiàn),一種簡單的做法可以是這樣的:

</>復(fù)制代碼

  1. function add(a){
  2. var sum = 0;
  3. sum += a;
  4. return function(b){
  5. sum += b;
  6. return function(c){
  7. sum += c;
  8. return sum;
  9. }
  10. }
  11. }
  12. add(1)(2)(3);//6

嗯,沒什么問題。

在此基礎(chǔ)上,我們再進(jìn)一步:

</>復(fù)制代碼

  1. 如果對調(diào)用的次數(shù)不加限制,比如 四次,那上面的代碼就不行了。
  2. 那該怎么辦呢?

觀察一下,我們可以發(fā)現(xiàn)返回的每一個函數(shù)執(zhí)行的邏輯其實(shí)都是一樣的。
就此我們可以精簡下代碼,讓函數(shù)返回后返回自身。

來試一下:

</>復(fù)制代碼

  1. function add(a){
  2. var sum = 0;
  3. sum += a;
  4. return function temp(b) {
  5. sum += b;
  6. return temp;
  7. }
  8. }
  9. add(2)(3)(4)(5);
  10. 輸出的結(jié)果:
  11. //function temp(b) {
  12. // sum += b;
  13. // return temp;
  14. // }

并沒有像我們預(yù)期的那樣輸出 14,其實(shí)是這樣的,每次函數(shù)調(diào)用后返回的就是一個函數(shù)對象,那最后的結(jié)果,肯定是一個字符串表示啊。

要修正的話,有兩個辦法。

判斷參數(shù),當(dāng)沒有輸入?yún)?shù)時,返回調(diào)用結(jié)果:

</>復(fù)制代碼

  1. function add(a){
  2. var sum = 0;
  3. sum += a;
  4. return function temp(b) {
  5. if (arguments.length === 0) {
  6. return sum;
  7. } else {
  8. sum= sum+ b;
  9. return temp;
  10. }
  11. }
  12. }
  13. add(2)(3)(4)(5)(); //14

如果要使用匿名函數(shù),也可以:

</>復(fù)制代碼

  1. function add() {
  2. var _args = [];
  3. return function(){
  4. if(arguments.length === 0) {
  5. return _args.reduce(function(a,b) {
  6. return a + b;
  7. });
  8. }
  9. [].push.apply(_args, [].slice.call(arguments));
  10. return arguments.callee;
  11. }
  12. }
  13. var sum = add();
  14. sum(2,3)(4)(5)(); //14

2 . 利用JS中對象到原始值的轉(zhuǎn)換規(guī)則。

</>復(fù)制代碼

  1. 當(dāng)一個對象轉(zhuǎn)換成原始值時,先查看對象是否有valueOf方法。
    如果有并且返回值是一個原始值,那么直接返回這個值。
    如果沒有valueOf 或 返回的不是原始值,那么調(diào)用toString方法,返回字符串表示。

那我們就為函數(shù)對象添加一個valueOf方法 和 toString方法:

</>復(fù)制代碼

  1. function add(a) {
  2. var sum = 0;
  3. sum += a;
  4. var temp = function(b) {
  5. if(arguments.length===0){
  6. return sum;
  7. } else {
  8. sum = sum+ b;
  9. return temp;
  10. }
  11. }
  12. temp.toString = temp.valueOf = function() {
  13. return sum;
  14. }
  15. return temp;
  16. }
  17. add(2)(3)(4)(5); //14

寫到這里,我們來簡單總結(jié)下。

柯里化的定義

</>復(fù)制代碼

  1. 柯里化通常也稱部分求值,其含義是給函數(shù)分步傳遞參數(shù),每次傳遞參數(shù)后,部分應(yīng)用參數(shù),并返回一個更具體的函數(shù)接受剩下的參數(shù),中間可嵌套多層這樣的接受部分參數(shù)函數(shù),逐步縮小函數(shù)的適用范圍,逐步求解,直至返回最后結(jié)果。
一個通用的柯里化函數(shù)

</>復(fù)制代碼

  1. var curring = function(fn){
  2. var _args = [];
  3. return function cb(){
  4. if(arguments.length === 0) {
  5. return fn.apply(this, _args);
  6. }
  7. Array.prototype.push.apply(_args, [].slice.call(arguments));
  8. return cb;
  9. }
  10. }
  11. var multi = function(){
  12. var total = 0;
  13. var argsArray = Array.prototype.slice.call(arguments);
  14. argsArray.forEach(function(item){
  15. total += item;
  16. })
  17. return total
  18. };
  19. var calc = curring(multi);
  20. calc(1,2)(3)(4,5,6);
  21. console.log(calc()); //空白調(diào)用時才真正計(jì)算

這樣 calc = currying(multi),調(diào)用非常清晰.
如果要 累加多個值,可以把多個值作為做個參數(shù) calc(1,2,3),也可以支持鏈?zhǔn)降恼{(diào)用,如 calc(1)(2)(3);

到這里, 不難看出,柯里化函數(shù)具有以下特點(diǎn):

函數(shù)可以作為參數(shù)傳遞

函數(shù)能夠作為函數(shù)的返回值

閉包

說了這么多,柯里化函數(shù)到底能夠幫我做什么,或者說,我為什么要用柯里化函數(shù)呢? 我們接著往下看。

柯里化函數(shù)的作用

</>復(fù)制代碼

  1. 函數(shù)柯里化允許和鼓勵你分隔復(fù)雜功能變成更小更容易分析的部分。這些小的邏輯單元顯然是更容易理解和測試的,然后你的應(yīng)用就會變成干凈而整潔的組合,由一些小單元組成的組合。

</>復(fù)制代碼

  1. 1.提高通用性

</>復(fù)制代碼

  1. function square(i) {
  2. return i * i;
  3. }
  4. function double(i) {
  5. return i *= 2;
  6. }
  7. function map(handeler, list) {
  8. return list.map(handeler);
  9. }
  10. // 數(shù)組的每一項(xiàng)平方
  11. map(square, [1, 2, 3, 4, 5]);
  12. map(square, [6, 7, 8, 9, 10]);
  13. map(square, [10, 20, 30, 40, 50]);
  14. // ......
  15. // 數(shù)組的每一項(xiàng)加倍
  16. map(double, [1, 2, 3, 4, 5]);
  17. map(double, [6, 7, 8, 9, 10]);
  18. map(double, [10, 20, 30, 40, 50]);

例子中,創(chuàng)建了一個map通用函數(shù),用于適應(yīng)不同的應(yīng)用場景。顯然,通用性不用懷疑。同時,例子中重復(fù)傳入了相同的處理函數(shù):square和dubble。

應(yīng)用中這種可能會更多。當(dāng)然,通用性的增強(qiáng)必然帶來適用性的減弱。但是,我們依然可以在中間找到一種平衡。

看下面,我們利用柯里化改造一下:

</>復(fù)制代碼

  1. function currying(fn) {
  2. var slice = Array.prototype.slice,
  3. __args = slice.call(arguments, 1);
  4. return function () {
  5. var __inargs = slice.call(arguments);
  6. return fn.apply(null, __args.concat(__inargs));
  7. };
  8. }
  9. function square(i) {
  10. return i * i;
  11. }
  12. function double(i) {
  13. return i *= 2;
  14. }
  15. function map(handeler, list) {
  16. return list.map(handeler);
  17. }
  18. var mapSQ = currying(map, square);
  19. mapSQ([1, 2, 3, 4, 5]); //[1, 4, 9, 16, 25]
  20. var mapDB = currying(map, double);
  21. mapDB([1, 2, 3, 4, 5]); //[2, 4, 6, 8, 10]

我們縮小了函數(shù)的適用范圍,但同時提高函數(shù)的適性.

2 延遲執(zhí)行。

</>復(fù)制代碼

  1. 柯里化的另一個應(yīng)用場景是延遲執(zhí)行。不斷的柯里化,累積傳入的參數(shù),最后執(zhí)行。

3.固定易變因素。

</>復(fù)制代碼

  1. 柯里化特性決定了它這應(yīng)用場景。提前把易變因素,傳參固定下來,生成一個更明確的應(yīng)用函數(shù)。最典型的代表應(yīng)用,是bind函數(shù)用以固定this這個易變對象。

</>復(fù)制代碼

  1. Function.prototype.bind = function(ctx) {
  2. var fn = this;
  3. return function() {
  4. fn.apply(ctx, arguments);
  5. };
  6. };

Function.prototype.bind 方法也是柯里化應(yīng)用與 call/apply 方法直接執(zhí)行不同,bind 方法 將第一個參數(shù)設(shè)置為函數(shù)執(zhí)行的上下文,其他參數(shù)依次傳遞給調(diào)用方法(函數(shù)的主體本身不執(zhí)行,可以看成是延遲執(zhí)行),并動態(tài)創(chuàng)建返回一個新的函數(shù), 這符合柯里化特點(diǎn)。

</>復(fù)制代碼

  1. var foo = {
  2. x: 666
  3. };
  4. var bar = function () {
  5. console.log(this.x);
  6. }.bind(foo); // 綁定
  7. bar(); //666
  8. // 下面是一個 bind 函數(shù)的模擬,testBind 創(chuàng)建并返回新的函數(shù),在新的函數(shù)中將真正要執(zhí)行業(yè)務(wù)的函數(shù)綁定到實(shí)參傳入的上下文,延遲執(zhí)行了。
  9. Function.prototype.testBind = function (scope) {
  10. var self = this; // this 指向的是調(diào)用 testBind 方法的一個函數(shù),
  11. return function () {
  12. return self.apply(scope);
  13. }
  14. };
  15. var testBindBar = bar.testBind(foo); // 綁定 foo,延遲執(zhí)行
  16. console.log(testBindBar); // Function (可見,bind之后返回的是一個延遲執(zhí)行的新函數(shù))
  17. testBindBar(); // 666
關(guān)于curry性能的備注

</>復(fù)制代碼

  1. 通常,使用柯里化會有一些開銷。取決于你正在做的是什么,可能會或不會,以明顯的方式影響你。也就是說,幾乎大多數(shù)情況,你的代碼的擁有性能瓶頸首先來自其他原因,而不是這個。

有關(guān)性能,這里有一些事情必須牢記于心:

存取arguments對象通常要比存取命名參數(shù)要慢一點(diǎn).

一些老版本的瀏覽器在arguments.length的實(shí)現(xiàn)上是相當(dāng)慢的.

創(chuàng)建大量嵌套作用域和閉包函數(shù)會帶來花銷,無論是在內(nèi)存還是速度上.

以上 ;)

參考資料

http://blog.jobbole.com/77956/
http://www.cnblogs.com/pigtai...

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/81424.html

相關(guān)文章

  • 高級函數(shù)技巧-函數(shù)柯里

    摘要:如果你對函數(shù)式編程有一定了解,函數(shù)柯里化是不可或缺的,利用函數(shù)柯里化,可以在開發(fā)中非常優(yōu)雅的處理復(fù)雜邏輯。同樣先看簡單版本的方法,以方法為例,代碼來自高級程序設(shè)計(jì)加強(qiáng)版實(shí)現(xiàn)上面函數(shù),可以換成任何其他函數(shù),經(jīng)過函數(shù)處理,都可以轉(zhuǎn)成柯里化函數(shù)。 我們經(jīng)常說在Javascript語言中,函數(shù)是一等公民,它們本質(zhì)上是十分簡單和過程化的。可以利用函數(shù),進(jìn)行一些簡單的數(shù)據(jù)處理,return 結(jié)果,...

    shixinzhang 評論0 收藏0
  • JS基礎(chǔ)之常用小技巧和知識總結(jié)(一)

    摘要:如果有一方是布爾值,則轉(zhuǎn)換為,轉(zhuǎn)換為,再進(jìn)行判斷。等同運(yùn)算符類型不同返回類型相同如果同為數(shù)字字符串則比較值如果同為布爾值,相同則為不同為如果兩個操作數(shù)同為引用類型,且引用的為同一個對象函數(shù),數(shù)組,則相同。 本文主要記錄平時開發(fā)遇到的知識點(diǎn)和小技巧 相等判斷(==) 類型相同: 判斷其值是否相同 類型不同: 1. 如果數(shù)字和字符串比較, 則字符串會被隱式轉(zhuǎn)換為數(shù)字,在做判斷。 2....

    dadong 評論0 收藏0
  • 高階函數(shù)應(yīng)用 —— 柯里與反柯里

    摘要:柯里化通用式上面的柯里化函數(shù)沒涉及到高階函數(shù),也不具備通用性,無法轉(zhuǎn)換形參個數(shù)任意或未知的函數(shù),我們接下來封裝一個通用的柯里化轉(zhuǎn)換函數(shù),可以將任意函數(shù)轉(zhuǎn)換成柯里化。 showImg(https://segmentfault.com/img/remote/1460000018998373); 閱讀原文 前言 在 JavaScript 中,柯里化和反柯里化是高階函數(shù)的一種應(yīng)用,在這之前...

    wyk1184 評論0 收藏0
  • 前端進(jìn)擊的巨人(五):學(xué)會函數(shù)柯里(curry)

    摘要:函數(shù)柯里化是把支持多個參數(shù)的函數(shù)變成接收單一參數(shù)的函數(shù),并返回一個函數(shù)能接收處理剩余參數(shù),而反柯里化就是把參數(shù)全部釋放出來。但在一些復(fù)雜的業(yè)務(wù)邏輯封裝中,函數(shù)柯里化能夠?yàn)槲覀兲峁└玫膽?yīng)對方案,讓我們的函數(shù)更具自由度和靈活性。 showImg(https://segmentfault.com/img/bVburN1?w=800&h=600); 柯里化(Curring, 以邏輯學(xué)家Has...

    chengtao1633 評論0 收藏0
  • JavaScript 函數(shù)式編程技巧 - 柯里

    摘要:作為函數(shù)式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。在一些函數(shù)式編程語言中,會定義一個特殊的占位變量。個人理解不知道對不對延遲執(zhí)行柯里化的另一個應(yīng)用場景是延遲執(zhí)行。不斷的柯里化,累積傳入的參數(shù),最后執(zhí)行。作為函數(shù)式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 這里可以對照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡介 柯里化(Currying)...

    edgardeng 評論0 收藏0

發(fā)表評論

0條評論

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