JavaScript函數柯裡化

來源:互聯網
上載者:User

標籤:

函數式

JavaScript是以函數為一等公民的函數式語言。函數在JavaScript中也是一個對象(繼承製Function),函數也可以作為參數傳遞成函數變數。最近幾年函數式也因為其無副作用的特性、透明性、惰性計算等在高並發,大資料領域火起來了。

JavaScript中也有如Underscore、lodash之類的函數式庫,如lodash的使用方式:

var names = _.chain(users)  .map(function(user){    return user.user;  })  .join(" , ")  .value();console.log(names);

關於lodash更多內容請參考JavaScript工具庫之Lodash.

柯裡化

今天文章將以高階函數中的柯裡化方式來,看看JavaScript的函數式能力。

在電腦科學中,柯裡化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受餘下的參數且返回結果的新函數的技術。這個技術由 Christopher Strachey 以邏輯學家 Haskell Curry 命名的,儘管它是 Moses Schnfinkel 和 Gottlob Frege 發明的。

在理論電腦科學中,柯裡化提供了在簡單的理論模型中比如只接受一個單一參數的lambda 演算中研究帶有多個參數的函數的方式。

JavaScript的柯裡化實現

下邊的例子,我們將把柯裡化方式泛化為接受任意個參數,直到聲明的方法參數個數飽和才執行,所以根據參數個數可以有多種柯裡化函數產生。

代碼如下:

(function(global) {    var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m,        FN_ARG_SPLIT = /,/,        FN_ARG = /^\s*(_?)(\S+?)\1\s*$/,        STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;    var getArgLength = function(func) {        var fnText = func.toString().replace(STRIP_COMMENTS, ‘‘);        var argDecl = fnText.match(FN_ARGS);        var params = [];        argDecl[1].split(FN_ARG_SPLIT).forEach(function(arg) {            arg.replace(FN_ARG, function(all, underscore, name) {                params.push(name);            });        });        return params.length;    };    var curryFunc = function(func, len) {        len = len || getArgLength(func);        var args = [];        if (len === 0) {            return func.apply(null);        }        return function() {            [].push.apply(args, [].slice.apply(arguments));            if (args.length >= len) {                return func.apply(null, args);            }            return arguments.callee;        };    };    global.curryFunc = curryFunc;})(this);function add(x, y, z) {    return x + y + z;}console.log("result 1:", curryFunc(add)(1, 2)(3));console.log("result 2:", curryFunc(add)(1)(2, 3));console.log("result 3:", curryFunc(add)(1)(3)(2));function add(x, y, z) {    return x * y * z;}console.log("result 1:", curryFunc(add)(2, 4)(6));console.log("result 2:", curryFunc(add)(2)(4, 6));console.log("result 3:", curryFunc(add)(2)(6)(4));function sayHello() {    return "hello";}console.log(curryFunc(sayHello));

首先上面會利用正則來擷取傳入函數的參數個數。再返回一個函數的代理,每次的調用都會將傳入參數緩衝在args臨時變數中,直到參數個數飽和才會立即執行。代碼比較冗長,慢慢品味,當然有不足支援,也希望大家指出來。

JavaScript函數柯裡化

聯繫我們

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